@financial-times/custom-code-component 1.9.3 → 1.9.5

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.
@@ -0,0 +1,24 @@
1
+ declare class Tracking {
2
+ cccId: string;
3
+ cccName: string;
4
+ subtype: string;
5
+ teamName: string;
6
+ shadowRoot: ShadowRoot | null;
7
+ category: string;
8
+ elements: string | string[];
9
+ isInitialised: boolean;
10
+ constructor({ id, name, subtype, teamName, shadowRoot, category, elements, }?: {
11
+ id?: string;
12
+ name?: string;
13
+ subtype?: string;
14
+ teamName?: string;
15
+ shadowRoot?: any;
16
+ category?: string;
17
+ elements?: string;
18
+ });
19
+ getEventProperties(event: any): {};
20
+ handleClickEvent(eventData: any, root: any): (clickEvent: any, clickElement: any) => void;
21
+ sendSpoorEvent(triggerAction: any, extraDetail: any): void;
22
+ init(id: any): void;
23
+ }
24
+ export default Tracking;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/custom-code-component",
3
- "version": "1.9.3",
3
+ "version": "1.9.5",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { ContentTree } from "@financial-times/content-tree";
7
7
  import { BaseRenderer } from "../../ccc-sdk/src/renderers/AbstractBaseRenderer";
8
- import tracking from "./analytics";
8
+ import Tracking from "./tracking";
9
9
 
10
10
  class FTCustomCodeComponent extends HTMLElement {
11
11
  app: typeof BaseRenderer.prototype.render;
@@ -24,6 +24,7 @@ class FTCustomCodeComponent extends HTMLElement {
24
24
  ]);
25
25
 
26
26
  source: string;
27
+ tracking: Tracking;
27
28
 
28
29
  async mount() {
29
30
  if (!this.app) {
@@ -45,6 +46,14 @@ class FTCustomCodeComponent extends HTMLElement {
45
46
  // Clear old children
46
47
  this.shadowRoot?.replaceChildren();
47
48
 
49
+ // Create tracking instance
50
+ this.tracking = new Tracking({
51
+ name: `${this.getAttribute("path")}@${this.getAttribute("version")}`,
52
+ subtype: "interactive",
53
+ teamName: "djd",
54
+ shadowRoot: this.shadowRoot as ShadowRoot,
55
+ });
56
+
48
57
  const { unmount, onmessage } =
49
58
  App(
50
59
  shadow,
@@ -52,7 +61,7 @@ class FTCustomCodeComponent extends HTMLElement {
52
61
  ...extraProps,
53
62
  data,
54
63
  port: this.channel.port2,
55
- tracking,
64
+ tracking: this.tracking,
56
65
  },
57
66
  ...this.children
58
67
  ) || {};
@@ -162,13 +171,7 @@ class FTCustomCodeComponent extends HTMLElement {
162
171
  }
163
172
 
164
173
  try {
165
- tracking.init(
166
- {
167
- id: this.getAttribute("path") as string,
168
- subtype: "interactive",
169
- },
170
- this.shadowRoot
171
- );
174
+ this.tracking.init(this.id);
172
175
  } catch (e) {
173
176
  console.info(
174
177
  `Error initialising tracking on <custom-code-component> ${path}@${componentVersionRange}`
@@ -0,0 +1,145 @@
1
+ import Delegate from "ftdomdelegate";
2
+ import oTracking from "@financial-times/o-tracking";
3
+ import { getTrace } from "./get-trace";
4
+ import {
5
+ sanitise,
6
+ assignIfUndefined,
7
+ } from "@financial-times/o-tracking/src/javascript/utils.js";
8
+
9
+ const eventPropertiesToCollect = ["ctrlKey", "altKey", "shiftKey", "metaKey"];
10
+
11
+ class Tracking {
12
+ cccId: string;
13
+ cccName: string;
14
+ subtype: string;
15
+ teamName: string;
16
+ shadowRoot: ShadowRoot | null;
17
+ category: string;
18
+ elements: string | string[];
19
+ isInitialised: boolean;
20
+
21
+ constructor({
22
+ id = "00000000-0000-0000-0000-000000000000",
23
+ name = "ccc-component",
24
+ subtype = "interactive",
25
+ teamName = "djd",
26
+ shadowRoot = null,
27
+ category = "cta",
28
+ elements = 'a, button, input, [role="button"]',
29
+ } = {}) {
30
+ this.cccId = id;
31
+ this.cccName = name;
32
+ this.subtype = subtype;
33
+ this.teamName = teamName;
34
+ this.shadowRoot = shadowRoot;
35
+ this.category = category;
36
+ this.elements = elements;
37
+ this.isInitialised = false;
38
+ }
39
+
40
+ // Get properties for the event (as opposed to properties of the clicked element)
41
+ getEventProperties(event) {
42
+ const eventProperties = {};
43
+ for (const property of eventPropertiesToCollect) {
44
+ if (event[property]) {
45
+ try {
46
+ eventProperties[property] = sanitise(event[property]);
47
+ } catch (e) {
48
+ console.log(e);
49
+ }
50
+ }
51
+ }
52
+ return eventProperties;
53
+ }
54
+
55
+ // Controller for handling click events
56
+ handleClickEvent(eventData, root) {
57
+ return (clickEvent, clickElement) => {
58
+ const context: any = this.getEventProperties(clickEvent);
59
+ const { trace, customContext } = getTrace(clickElement, root);
60
+ context.custom =
61
+ clickElement.dataset && clickElement.dataset.custom
62
+ ? JSON.parse(clickElement.dataset.custom)
63
+ : null;
64
+ context.domPathTokens = trace;
65
+ context.component = {
66
+ id: this.cccId,
67
+ name: this.cccName,
68
+ type: "custom-code-component",
69
+ subtype: this.subtype,
70
+ };
71
+ context.teamName = this.teamName;
72
+
73
+ assignIfUndefined(customContext, context);
74
+
75
+ eventData.context = context;
76
+ eventData.method = "ftCustomAnalytics";
77
+
78
+ // send spoor event
79
+ document.body.dispatchEvent(
80
+ new CustomEvent("oTracking.event", {
81
+ detail: eventData,
82
+ bubbles: true,
83
+ composed: true,
84
+ })
85
+ );
86
+ };
87
+ }
88
+
89
+ sendSpoorEvent(triggerAction, extraDetail) {
90
+ const eventData = {
91
+ category: "component",
92
+ action: "act",
93
+ context: {
94
+ component: {
95
+ id: this.cccId,
96
+ name: this.cccName,
97
+ type: "custom-code-component",
98
+ subtype: this.subtype,
99
+ },
100
+ teamName: this.teamName,
101
+ trigger_action: triggerAction,
102
+ custom: extraDetail,
103
+ },
104
+ method: "ftCustomAnalytics",
105
+ };
106
+
107
+ // send spoor event
108
+ document.body.dispatchEvent(
109
+ new CustomEvent("oTracking.event", {
110
+ detail: eventData,
111
+ bubbles: true,
112
+ composed: true,
113
+ })
114
+ );
115
+ }
116
+
117
+ init(id) {
118
+ if (!this.isInitialised) {
119
+ this.isInitialised = true;
120
+ this.cccId = id ? id : this.cccId;
121
+
122
+ oTracking.init({ queue: true, test: true }); // @TODO: Flip this to false before using in production
123
+
124
+ const eventData = {
125
+ action: "click",
126
+ category: this.category,
127
+ };
128
+
129
+ const root = this.shadowRoot?.querySelector("#component-root");
130
+
131
+ if (this.shadowRoot) {
132
+ const shadowDelegate = new Delegate(root);
133
+
134
+ shadowDelegate.on(
135
+ "click",
136
+ this.elements,
137
+ this.handleClickEvent(eventData, root),
138
+ true
139
+ );
140
+ }
141
+ }
142
+ }
143
+ }
144
+
145
+ export default Tracking;
@@ -1,11 +0,0 @@
1
- declare function sendSpoorEvent(triggerAction: any, extraDetail: any): void;
2
- declare function init(templateObj: {
3
- id?: string;
4
- subtype?: string;
5
- }, shadowRoot?: ShadowRoot, category?: string, elements?: []): void;
6
- declare const tracking: {
7
- init: typeof init;
8
- isInitialised: boolean;
9
- sendSpoorEvent: typeof sendSpoorEvent;
10
- };
11
- export default tracking;
package/src/analytics.ts DELETED
@@ -1,137 +0,0 @@
1
- import Delegate from "ftdomdelegate";
2
- import oTracking from "@financial-times/o-tracking";
3
- import { getTrace } from "./get-trace";
4
- import {
5
- sanitise,
6
- assignIfUndefined,
7
- } from "@financial-times/o-tracking/src/javascript/utils.js";
8
-
9
- // default values if nothing is passed into init
10
- let cccName = "ccc-component";
11
- let subtype = "interactive";
12
-
13
- const eventPropertiesToCollect = ["ctrlKey", "altKey", "shiftKey", "metaKey"];
14
-
15
- // Get properties for the event (as opposed to properties of the clicked element)
16
- // Available properties include mouse x- and y co-ordinates, for example.
17
- const getEventProperties = (event) => {
18
- const eventProperties = {};
19
- for (const property of eventPropertiesToCollect) {
20
- if (event[property]) {
21
- try {
22
- eventProperties[property] = sanitise(event[property]);
23
- } catch (e) {
24
- // eslint-disable-next-line no-console
25
- console.log(e);
26
- }
27
- }
28
- }
29
-
30
- return eventProperties;
31
- };
32
-
33
- // Controller for handling click events
34
- const handleClickEvent = (eventData, root) => (clickEvent, clickElement) => {
35
- const context = getEventProperties(clickEvent);
36
- const { trace, customContext } = getTrace(clickElement, root);
37
- context.custom =
38
- clickElement.dataset && clickElement.dataset.custom
39
- ? JSON.parse(clickElement.dataset.custom)
40
- : null;
41
- context.domPathTokens = trace;
42
- context.component = {
43
- id: cccName,
44
- name: cccName,
45
- type: "custom-code-component",
46
- subtype,
47
- };
48
- context.teamName = "djd";
49
-
50
- assignIfUndefined(customContext, context);
51
-
52
- eventData.context = context;
53
- eventData.method = "ftCustomAnalytics";
54
-
55
- // send spoor event
56
- document.body.dispatchEvent(
57
- new CustomEvent("oTracking.event", {
58
- detail: eventData,
59
- bubbles: true,
60
- composed: true,
61
- })
62
- );
63
- };
64
-
65
- function sendSpoorEvent(triggerAction, extraDetail) {
66
- const eventData = {
67
- category: "component",
68
- action: "act",
69
- context: {
70
- component: {
71
- id: cccName,
72
- name: cccName,
73
- type: "custom-code-component",
74
- subtype,
75
- },
76
- teamName: "djd",
77
- trigger_action: triggerAction,
78
- custom: extraDetail,
79
- },
80
- method: "ftCustomAnalytics",
81
- };
82
-
83
- // send spoor event
84
- document.body.dispatchEvent(
85
- new CustomEvent("oTracking.event", {
86
- detail: eventData,
87
- bubbles: true,
88
- composed: true,
89
- })
90
- );
91
- }
92
-
93
- function init(
94
- templateObj: { id?: string; subtype?: string },
95
- shadowRoot?: ShadowRoot,
96
- category?: string,
97
- elements?: []
98
- ) {
99
- if (!tracking.isInitialised) {
100
- tracking.isInitialised = true;
101
- if (templateObj) {
102
- cccName = templateObj.id || cccName;
103
- subtype = templateObj.subtype || subtype;
104
- }
105
-
106
- oTracking.init({ queue: true, test: true }); // @TODO: Flip this to false before using in production
107
-
108
- const elementsToTrack = elements || 'a, button, input, [role="button"]';
109
-
110
- // Note: `context` is the term o-tracking uses for the data that is sent to spoor
111
- const eventData = {
112
- action: "click",
113
- category: category || "cta",
114
- };
115
-
116
- const root = shadowRoot?.querySelector("#component-root");
117
-
118
- if (shadowRoot) {
119
- const shadowDelegate = new Delegate(root);
120
-
121
- shadowDelegate.on(
122
- "click",
123
- elementsToTrack,
124
- handleClickEvent(eventData, root),
125
- true
126
- );
127
- }
128
- }
129
- }
130
-
131
- const tracking = {
132
- init,
133
- isInitialised: false,
134
- sendSpoorEvent,
135
- };
136
-
137
- export default tracking;