@simplybusiness/services 0.8.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/cjs/mocks/eventDefinitions.js +39 -0
  3. package/dist/cjs/mocks/eventDefinitions.js.map +1 -1
  4. package/dist/cjs/snowplow/Snowplow.js +13 -2
  5. package/dist/cjs/snowplow/Snowplow.js.map +1 -1
  6. package/dist/cjs/snowplow/event-definitions/base.js +39 -0
  7. package/dist/cjs/snowplow/event-definitions/base.js.map +1 -1
  8. package/dist/cjs/snowplow/event-definitions/index.js +9 -2
  9. package/dist/cjs/snowplow/event-definitions/index.js.map +1 -1
  10. package/dist/cjs/snowplow/event-definitions/qcp.js +14 -0
  11. package/dist/cjs/snowplow/event-definitions/qcp.js.map +1 -1
  12. package/dist/cjs/snowplow/event-definitions/questionnaire.js +49 -0
  13. package/dist/cjs/snowplow/event-definitions/questionnaire.js.map +1 -0
  14. package/dist/cjs/snowplow/event-definitions/redaction.js +152 -0
  15. package/dist/cjs/snowplow/event-definitions/redaction.js.map +1 -0
  16. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  17. package/dist/esm/mocks/eventDefinitions.js +39 -0
  18. package/dist/esm/mocks/eventDefinitions.js.map +1 -1
  19. package/dist/esm/snowplow/Snowplow.js +13 -2
  20. package/dist/esm/snowplow/Snowplow.js.map +1 -1
  21. package/dist/esm/snowplow/event-definitions/base.js +39 -0
  22. package/dist/esm/snowplow/event-definitions/base.js.map +1 -1
  23. package/dist/esm/snowplow/event-definitions/index.js +6 -2
  24. package/dist/esm/snowplow/event-definitions/index.js.map +1 -1
  25. package/dist/esm/snowplow/event-definitions/qcp.js +14 -0
  26. package/dist/esm/snowplow/event-definitions/qcp.js.map +1 -1
  27. package/dist/esm/snowplow/event-definitions/questionnaire.js +40 -0
  28. package/dist/esm/snowplow/event-definitions/questionnaire.js.map +1 -0
  29. package/dist/esm/snowplow/event-definitions/redaction.js +142 -0
  30. package/dist/esm/snowplow/event-definitions/redaction.js.map +1 -0
  31. package/dist/esm/snowplow/types.js.map +1 -1
  32. package/dist/types/mocks/eventDefinitions.d.ts +30 -0
  33. package/dist/types/snowplow/Snowplow.d.ts +1 -0
  34. package/dist/types/snowplow/event-definitions/index.d.ts +1 -0
  35. package/dist/types/snowplow/event-definitions/questionnaire.d.ts +2 -0
  36. package/dist/types/snowplow/event-definitions/redaction.d.ts +5 -0
  37. package/dist/types/snowplow/types.d.ts +15 -1
  38. package/package.json +1 -1
  39. package/src/mocks/eventDefinitions.ts +44 -0
  40. package/src/snowplow/Snowplow.ts +16 -2
  41. package/src/snowplow/event-definitions/base.ts +43 -2
  42. package/src/snowplow/event-definitions/index.ts +4 -0
  43. package/src/snowplow/event-definitions/qcp.ts +17 -1
  44. package/src/snowplow/event-definitions/questionnaire.ts +43 -0
  45. package/src/snowplow/event-definitions/redaction.ts +144 -0
  46. package/src/snowplow/index.test.ts +179 -6
  47. package/src/snowplow/types.ts +17 -15
@@ -0,0 +1,144 @@
1
+ import { ParamsType } from "../types";
2
+
3
+ const PII_ANSWER = [
4
+ "customer_title",
5
+ "customer_first_name",
6
+ "customer_last_name",
7
+ "customer_email_address",
8
+ "preapp_email_address",
9
+ "customer_telephone_number",
10
+ "customer_alternative_telephone_number",
11
+ "customer_address_1_pre_quote",
12
+ "customer_address_2_pre_quote",
13
+ "customer_town_pre_quote",
14
+ "customer_postcode_pre_quote",
15
+ "customer_address_1",
16
+ "customer_address_2",
17
+ "customer_town",
18
+ "customer_postcode",
19
+ "address_1_pre_quote",
20
+ "address_2_pre_quote",
21
+ "uk_postcode_pre_quote",
22
+ "town_pre_quote",
23
+ "owner_first_name",
24
+ "owner_last_name",
25
+ "beneficiary_first_name",
26
+ "beneficiary_last_name",
27
+ "gender",
28
+ "dynamic_ssn_fein",
29
+ "ssn",
30
+ "fein",
31
+ "sof_county_court_judgement_online_yes",
32
+ "sof_county_court_judgement_online_no",
33
+ "sof_ccj_count",
34
+ "sof_ccj_value",
35
+ "sof_ccj_date",
36
+ "sof_court_judgement_yes",
37
+ "sof_court_judgement_no",
38
+ "ccj_date",
39
+ "sof_single_ccj_no",
40
+ "sof_single_ccj_yes",
41
+ "sof_ccj_yes",
42
+ "sof_ccj_no",
43
+ "ccj_count",
44
+ "sof_bankrupt_yes",
45
+ "sof_bankrupt_no",
46
+ "sof_multiple_bankruptcies_yes",
47
+ "sof_multiple_bankruptcies_no",
48
+ "bankruptcy_date",
49
+ "sof_single_bankruptcy_no",
50
+ "sof_single_bankruptcy_yes",
51
+ "sof_bankruptcy_yes",
52
+ "sof_bankruptcy_no",
53
+ "bankruptcy_discharged",
54
+ "sof_liquidation_yes",
55
+ "sof_liquidation_no",
56
+ "sof_multiple_liquidations",
57
+ "liquidation_date",
58
+ "sof_criminal_offence_yes",
59
+ "sof_criminal_offence_no",
60
+ "sof_criminal_yes",
61
+ "sof_criminal_no",
62
+ "hcp_date_of_birth_1",
63
+ "hcp_date_of_birth_2",
64
+ "hcp_date_of_birth_3",
65
+ "hcp_date_of_birth_4",
66
+ "hcp_date_of_birth_5",
67
+ "hcp_date_of_birth_6",
68
+ "hcp_date_of_birth_7",
69
+ "hcp_date_of_birth_8",
70
+ "hcp_date_of_birth_9",
71
+ "hcp_date_of_birth_10",
72
+ "sof_previous_claims_yes",
73
+ "sof_previous_claims_no",
74
+ "sof_claims_yes",
75
+ "sof_claims_no",
76
+ "sof_property_claims_in_the_last_5_years_yes",
77
+ "sof_property_claims_in_the_last_5_years_no",
78
+ "sof_property_claims_in_the_last_0_to_4_years_yes",
79
+ "sof_property_claims_in_the_last_0_to_4_years_no",
80
+ "claim_count",
81
+ "sof_number_of_claims",
82
+ "number_of_claims_in_last_5_years",
83
+ "number_of_claims_in_time_owned",
84
+ "date_of_incident_1",
85
+ "date_of_incident_2",
86
+ "date_of_incident_3",
87
+ "date_of_incident_4",
88
+ "date_of_incident_5",
89
+ "type_of_incident_1",
90
+ "type_of_incident_2",
91
+ "type_of_incident_3",
92
+ "type_of_incident_4",
93
+ "type_of_incident_5",
94
+ "incident_value_1",
95
+ "incident_value_2",
96
+ "incident_value_3",
97
+ "incident_value_4",
98
+ "incident_value_5",
99
+ "sof_pollution_disease_claims_yes",
100
+ "sof_pollution_disease_claims_no",
101
+ "sof_potential_claims_yes",
102
+ "sof_potential_claims_no",
103
+ "sof_previous_circumstances_yes",
104
+ "sof_previous_circumstances_no",
105
+ "sof_possible_claims_yes",
106
+ "sof_possible_claims_no",
107
+ "date_of_possible_incident",
108
+ "type_of_possible_incident",
109
+ "possible_incident_value",
110
+ "sof_property_claims_yes",
111
+ "sof_property_claims_no",
112
+ "sof_liability_claims_yes",
113
+ "sof_liability_claims_no",
114
+ "van_registration",
115
+ "sof_disqualified_director_yes",
116
+ "sof_disqualified_director_no",
117
+ "sof_insurance_refused_yes",
118
+ "sof_insurance_refused_no",
119
+ "sof_insurance_declined_yes",
120
+ "sof_insurance_declined_no",
121
+ "insurance_refused",
122
+ ];
123
+
124
+ const RADIO_ANSWER_FROM_QUESTIONS = [
125
+ "have_secondary_trade_yes",
126
+ "have_secondary_trade_no",
127
+ ];
128
+
129
+ const ANSWER_SUFFIX_PATTERN = /_(yes|no)$/;
130
+
131
+ export const redact = (params: ParamsType) => {
132
+ let { question, answer } = params as ParamsType;
133
+
134
+ const piiAnswer = new Set(PII_ANSWER);
135
+ const radioAnswerFromQuestions = new Set(RADIO_ANSWER_FROM_QUESTIONS);
136
+
137
+ if (piiAnswer.has(question)) {
138
+ answer = "REDACTED";
139
+ question = question?.replace(ANSWER_SUFFIX_PATTERN, "");
140
+ } else if (radioAnswerFromQuestions.has(question)) {
141
+ question = question?.replace(ANSWER_SUFFIX_PATTERN, "");
142
+ }
143
+ return { question, answer };
144
+ };
@@ -118,6 +118,7 @@ describe("Snowplow Analytics Class", () => {
118
118
  expect(Object.keys(testSnowplow.eventHandlers)).toEqual([
119
119
  "navButtonClicked",
120
120
  "questionAnswered",
121
+ "helpTextOpened",
121
122
  ]);
122
123
  });
123
124
 
@@ -159,20 +160,192 @@ describe("Snowplow Analytics Class", () => {
159
160
  .mockImplementation(() => {});
160
161
 
161
162
  await testSnowplow.trigger("questionAnswered", {
162
- vertical: "shop",
163
163
  question: "test-question",
164
+ section: "test-section",
164
165
  answer: "test-answer",
165
166
  });
166
167
 
167
168
  const expectedPayload = {
168
169
  schema:
169
- "iglu:com.simplybusiness/form_question_answered/jsonschema/1-0-1",
170
+ "iglu:com.simplybusiness/form_question_answered/jsonschema/1-0-3",
170
171
  data: {
171
- site: "",
172
- vertical: "shop",
172
+ site: "simplybusiness_us",
173
+ vertical: "usa",
173
174
  page_index: 1,
174
- page_name: "Coverage diagnosis questionnaire",
175
- section_name: "Coverage diagnosis questionnaire",
175
+ page_name: "quick_to_quote",
176
+ section_name: "test-section",
177
+ submitted_from: "quick_to_quote_experiment",
178
+ question: "test-question",
179
+ answer: "test-answer",
180
+ },
181
+ };
182
+
183
+ expect(trackUnstructEventSpy).toHaveBeenCalledTimes(1);
184
+ expect(trackUnstructEventSpy).toHaveBeenCalledWith(expectedPayload);
185
+ expect(innerSpy).toHaveBeenCalledTimes(1);
186
+ expect(innerSpy).toHaveBeenCalledWith(
187
+ {
188
+ event: expectedPayload,
189
+ context: contexts,
190
+ },
191
+ ["sb-ava"],
192
+ );
193
+ });
194
+
195
+ it("triggers an added unstructured event and readact the pii information and replace question name", async () => {
196
+ testSnowplow.addEventHandlers(eventDefinitions as EventDefinition[]);
197
+
198
+ const trackUnstructEventSpy = jest.spyOn(
199
+ testSnowplow,
200
+ "trackUnstructEvent",
201
+ );
202
+ const innerSpy = jest
203
+ .spyOn(SnowplowLib, "trackSelfDescribingEvent")
204
+ .mockImplementation(() => {});
205
+
206
+ await testSnowplow.trigger("questionAnswered", {
207
+ question: "sof_bankrupt_yes",
208
+ section: "agreements",
209
+ answer: "Yes",
210
+ });
211
+
212
+ const expectedPayload = {
213
+ schema:
214
+ "iglu:com.simplybusiness/form_question_answered/jsonschema/1-0-3",
215
+ data: {
216
+ site: "simplybusiness_us",
217
+ vertical: "usa",
218
+ page_index: 1,
219
+ page_name: "quick_to_quote",
220
+ section_name: "agreements",
221
+ submitted_from: "quick_to_quote_experiment",
222
+ question: "sof_bankrupt",
223
+ answer: "REDACTED",
224
+ },
225
+ };
226
+
227
+ expect(trackUnstructEventSpy).toHaveBeenCalledTimes(1);
228
+ expect(trackUnstructEventSpy).toHaveBeenCalledWith(expectedPayload);
229
+ expect(innerSpy).toHaveBeenCalledTimes(1);
230
+ expect(innerSpy).toHaveBeenCalledWith(
231
+ {
232
+ event: expectedPayload,
233
+ context: contexts,
234
+ },
235
+ ["sb-ava"],
236
+ );
237
+ });
238
+
239
+ it("triggers an added unstructured event and replace radio answer from questions", async () => {
240
+ testSnowplow.addEventHandlers(eventDefinitions as EventDefinition[]);
241
+
242
+ const trackUnstructEventSpy = jest.spyOn(
243
+ testSnowplow,
244
+ "trackUnstructEvent",
245
+ );
246
+ const innerSpy = jest
247
+ .spyOn(SnowplowLib, "trackSelfDescribingEvent")
248
+ .mockImplementation(() => {});
249
+
250
+ await testSnowplow.trigger("questionAnswered", {
251
+ question: "have_secondary_trade_yes",
252
+ section: "about_your_business",
253
+ answer: "Yes",
254
+ });
255
+
256
+ const expectedPayload = {
257
+ schema:
258
+ "iglu:com.simplybusiness/form_question_answered/jsonschema/1-0-3",
259
+ data: {
260
+ site: "simplybusiness_us",
261
+ vertical: "usa",
262
+ page_index: 1,
263
+ page_name: "quick_to_quote",
264
+ section_name: "about_your_business",
265
+ submitted_from: "quick_to_quote_experiment",
266
+ question: "have_secondary_trade",
267
+ answer: "Yes",
268
+ },
269
+ };
270
+
271
+ expect(trackUnstructEventSpy).toHaveBeenCalledTimes(1);
272
+ expect(trackUnstructEventSpy).toHaveBeenCalledWith(expectedPayload);
273
+ expect(innerSpy).toHaveBeenCalledTimes(1);
274
+ expect(innerSpy).toHaveBeenCalledWith(
275
+ {
276
+ event: expectedPayload,
277
+ context: contexts,
278
+ },
279
+ ["sb-ava"],
280
+ );
281
+ });
282
+
283
+ it("triggers an added unstructured help_text_opened event", async () => {
284
+ testSnowplow.addEventHandlers(eventDefinitions as EventDefinition[]);
285
+
286
+ const trackUnstructEventSpy = jest.spyOn(
287
+ testSnowplow,
288
+ "trackUnstructEvent",
289
+ );
290
+ const innerSpy = jest
291
+ .spyOn(SnowplowLib, "trackSelfDescribingEvent")
292
+ .mockImplementation(() => {});
293
+
294
+ await testSnowplow.trigger("helpTextOpened", {
295
+ primaryText: "Sample text",
296
+ label: "Sample label",
297
+ });
298
+
299
+ const expectedPayload = {
300
+ schema: "iglu:com.simplybusiness/help_text_opened/jsonschema/1-1-0",
301
+ data: {
302
+ vertical: "usa",
303
+ site: "simplybusiness_us",
304
+ primary_text: "Sample text",
305
+ label: "Sample label",
306
+ page_name: "quick_to_quote",
307
+ },
308
+ };
309
+
310
+ expect(trackUnstructEventSpy).toHaveBeenCalledTimes(1);
311
+ expect(trackUnstructEventSpy).toHaveBeenCalledWith(expectedPayload);
312
+ expect(innerSpy).toHaveBeenCalledTimes(1);
313
+ expect(innerSpy).toHaveBeenCalledWith(
314
+ {
315
+ event: expectedPayload,
316
+ context: contexts,
317
+ },
318
+ ["sb-ava"],
319
+ );
320
+ });
321
+
322
+ it("uses server-supplied context in events", async () => {
323
+ testSnowplow.addEventHandlers(eventDefinitions as EventDefinition[]);
324
+
325
+ const trackUnstructEventSpy = jest.spyOn(
326
+ testSnowplow,
327
+ "trackUnstructEvent",
328
+ );
329
+ const innerSpy = jest
330
+ .spyOn(SnowplowLib, "trackSelfDescribingEvent")
331
+ .mockImplementation(() => {});
332
+
333
+ await testSnowplow.trigger("questionAnswered", {
334
+ question: "test-question",
335
+ section: "test-section",
336
+ answer: "test-answer",
337
+ });
338
+
339
+ const expectedPayload = {
340
+ schema:
341
+ "iglu:com.simplybusiness/form_question_answered/jsonschema/1-0-3",
342
+ data: {
343
+ site: "simplybusiness_us",
344
+ vertical: "usa",
345
+ page_index: 1,
346
+ page_name: "quick_to_quote",
347
+ section_name: "test-section",
348
+ submitted_from: "quick_to_quote_experiment",
176
349
  question: "test-question",
177
350
  answer: "test-answer",
178
351
  },
@@ -21,6 +21,7 @@ export type EnvConfig = BaseConfig & {
21
21
  export type TrackingProps = BaseConfig & {
22
22
  eventMethod: EventMethod;
23
23
  cookieDomain?: string;
24
+ pageViewContext?: ChannelContext;
24
25
  };
25
26
 
26
27
  export type ChannelContext = {
@@ -32,21 +33,22 @@ export type ChannelContexts = Record<string, ChannelContext>;
32
33
 
33
34
  export type ArrayOneOrMore<T> = [T, ...T[]];
34
35
 
35
- export type ParamsType = Record<
36
- | "label"
37
- | "deviceType"
38
- | "category"
39
- | "product"
40
- | "title"
41
- | "label"
42
- | "name"
43
- | "fromValue"
44
- | "toValue"
45
- | "url"
46
- | "journeyId"
47
- | "vertical",
48
- string
49
- >;
36
+ export type ParamsType = Record<string, string> & {
37
+ context: ServerContext;
38
+ };
39
+
40
+ type ServerContext = {
41
+ site: string;
42
+ vertical: string;
43
+ primary_detail: string;
44
+ journey_name: string;
45
+ journey_id: string;
46
+ };
47
+
48
+ export type LinkType = Record<string, string> & {
49
+ targetUrl: string;
50
+ elementContent: string;
51
+ };
50
52
 
51
53
  export type EventDefinition = {
52
54
  name: string;