Skip to content

Commit 5a4b81d

Browse files
igneel64greg-el
authored andcommitted
Allow disabling activity tracking actions (close #1161)
#1224
1 parent e97528c commit 5a4b81d

File tree

7 files changed

+149
-7
lines changed

7 files changed

+149
-7
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@snowplow/browser-tracker-core",
5+
"comment": "Allow disabling activity tracking actions with disableActivityTracking and disableActivityTrackingCallback APIs",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@snowplow/browser-tracker-core"
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@snowplow/browser-tracker",
5+
"comment": "Allow disabling activity tracking actions with disableActivityTracking and disableActivityTrackingCallback APIs",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@snowplow/browser-tracker"
10+
}

libraries/browser-tracker-core/src/tracker/index.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,20 +1048,20 @@ export function Tracker(
10481048
//Clear page ping heartbeat on new page view
10491049
window.clearInterval(config.activityInterval);
10501050

1051-
activityInterval(config, context, contextCallback);
1051+
scheduleActivityInterval(config, context, contextCallback);
10521052
}
10531053
}
10541054
}
10551055
}
10561056

1057-
function activityInterval(
1057+
function scheduleActivityInterval(
10581058
config: ActivityConfig,
10591059
context?: Array<SelfDescribingJson> | null,
10601060
contextCallback?: (() => Array<SelfDescribingJson>) | null
10611061
) {
1062-
const executePagePing = (cb: ActivityCallback, c: Array<SelfDescribingJson>) => {
1062+
const executePagePing = (cb: ActivityCallback, context: Array<SelfDescribingJson>) => {
10631063
refreshUrl();
1064-
cb({ context: c, pageViewId: getPageViewId(), minXOffset, minYOffset, maxXOffset, maxYOffset });
1064+
cb({ context, pageViewId: getPageViewId(), minXOffset, minYOffset, maxXOffset, maxYOffset });
10651065
resetMaxScrolls();
10661066
};
10671067

@@ -1087,10 +1087,10 @@ export function Tracker(
10871087
}
10881088
};
10891089

1090-
if (config.configMinimumVisitLength != 0) {
1091-
config.activityInterval = window.setTimeout(timeout, config.configMinimumVisitLength);
1092-
} else {
1090+
if (config.configMinimumVisitLength === 0) {
10931091
config.activityInterval = window.setInterval(heartbeat, config.configHeartBeatTimer);
1092+
} else {
1093+
config.activityInterval = window.setTimeout(timeout, config.configMinimumVisitLength);
10941094
}
10951095
}
10961096

@@ -1137,6 +1137,17 @@ export function Tracker(
11371137
);
11381138
}
11391139

1140+
function disableActivityTrackingAction(actionKey: keyof ActivityConfigurations) {
1141+
const callbackConfiguration = activityTrackingConfig.configurations[actionKey];
1142+
if (callbackConfiguration?.configMinimumVisitLength === 0) {
1143+
window.clearTimeout(callbackConfiguration?.activityInterval);
1144+
} else {
1145+
window.clearInterval(callbackConfiguration?.activityInterval);
1146+
}
1147+
1148+
activityTrackingConfig.configurations[actionKey] = undefined;
1149+
}
1150+
11401151
const apiMethods = {
11411152
getDomainSessionIndex: function () {
11421153
return memorizedVisitCount;
@@ -1219,6 +1230,14 @@ export function Tracker(
12191230
}
12201231
},
12211232

1233+
disableActivityTracking: function () {
1234+
disableActivityTrackingAction('pagePing');
1235+
},
1236+
1237+
disableActivityTrackingCallback: function () {
1238+
disableActivityTrackingAction('callback');
1239+
},
1240+
12221241
updatePageActivity: function () {
12231242
activityHandler();
12241243
},

libraries/browser-tracker-core/src/tracker/types.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,16 @@ export interface BrowserTracker {
481481
configuration: ActivityTrackingConfiguration & ActivityTrackingConfigurationCallback
482482
) => void;
483483

484+
/**
485+
* Disables page activity tracking.
486+
*/
487+
disableActivityTracking: () => void;
488+
489+
/**
490+
* Disables page activity tracking callback.
491+
*/
492+
disableActivityTrackingCallback: () => void;
493+
484494
/**
485495
* Triggers the activityHandler manually to allow external user defined
486496
* activity. i.e. While watching a video

trackers/browser-tracker/docs/browser-tracker.api.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,8 @@ export interface BrowserTracker {
6363
// Warning: (ae-forgotten-export) The symbol "TrackerCore" needs to be exported by the entry point index.module.d.ts
6464
core: TrackerCore;
6565
crossDomainLinker: (crossDomainLinkerCriterion: (elt: HTMLAnchorElement | HTMLAreaElement) => boolean) => void;
66+
disableActivityTracking: () => void;
67+
disableActivityTrackingCallback: () => void;
6668
disableAnonymousTracking: (configuration?: DisableAnonymousTrackingConfiguration) => void;
6769
discardBrace: (enableFilter: boolean) => void;
6870
discardHashTag: (enableFilter: boolean) => void;
@@ -172,6 +174,12 @@ export type CookieSameSite = "None" | "Lax" | "Strict";
172174
// @public
173175
export function crossDomainLinker(crossDomainLinkerCriterion: (elt: HTMLAnchorElement | HTMLAreaElement) => boolean, trackers?: Array<string>): void;
174176

177+
// @public
178+
export function disableActivityTracking(trackers?: Array<string>): void;
179+
180+
// @public
181+
export function disableActivityTrackingCallback(trackers?: Array<string>): void;
182+
175183
// @public
176184
export function disableAnonymousTracking(configuration?: DisableAnonymousTrackingConfiguration, trackers?: Array<string>): void;
177185

trackers/browser-tracker/src/api.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,28 @@ export function enableActivityTrackingCallback(
226226
});
227227
}
228228

229+
/**
230+
* Disables page activity tracking.
231+
*
232+
* @param trackers - The tracker identifiers the activity tracking will be disabled.
233+
*/
234+
export function disableActivityTracking(trackers?: Array<string>) {
235+
dispatchToTrackers(trackers, (t) => {
236+
t.disableActivityTracking();
237+
});
238+
}
239+
240+
/**
241+
* Disables page activity tracking callback.
242+
*
243+
* @param trackers - The tracker identifiers the activity tracking callback will be disabled.
244+
*/
245+
export function disableActivityTrackingCallback(trackers?: Array<string>) {
246+
dispatchToTrackers(trackers, (t) => {
247+
t.disableActivityTrackingCallback();
248+
});
249+
}
250+
229251
/**
230252
* Triggers the activityHandler manually to allow external user defined activity. i.e. While watching a video
231253
*

trackers/browser-tracker/test/tracker.test.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,4 +275,67 @@ describe('Activity tracker behaviour', () => {
275275
expect(firstPageId).toBe(extractPageId(pph));
276276
expect(secondPageId).toBe(extractPageId(ppl));
277277
});
278+
279+
it('disables activity tracking', () => {
280+
const state = new SharedState();
281+
const t =
282+
addTracker('sp6', 'sp6', '', '', state, { stateStorageStrategy: 'cookie' }) ?? fail('Failed to create tracker');
283+
t.enableActivityTracking({ minimumVisitLength: 5, heartbeatDelay: 5 });
284+
t.trackPageView();
285+
286+
jest.advanceTimersByTime(100);
287+
t.updatePageActivity();
288+
jest.advanceTimersByTime(4900);
289+
290+
expect(F.size(getPPEvents(state.outQueues))).toBe(1);
291+
292+
// page ping timer starts tracking
293+
jest.advanceTimersByTime(100);
294+
t.updatePageActivity();
295+
jest.advanceTimersByTime(4900);
296+
297+
expect(F.size(getPPEvents(state.outQueues))).toBe(2);
298+
299+
/* Disabling activity tracking and callback is expected to not allow more activity actions */
300+
t.disableActivityTracking();
301+
t.disableActivityTrackingCallback();
302+
303+
jest.advanceTimersByTime(100);
304+
t.updatePageActivity();
305+
jest.advanceTimersByTime(4900);
306+
307+
expect(F.size(getPPEvents(state.outQueues))).toBe(2);
308+
});
309+
310+
it('disables activity tracking callback', () => {
311+
let callbacks = 0;
312+
const state = new SharedState();
313+
const t =
314+
addTracker('sp7', 'sp7', '', '', state, { stateStorageStrategy: 'cookie' }) ?? fail('Failed to create tracker');
315+
t.enableActivityTrackingCallback({ minimumVisitLength: 5, heartbeatDelay: 5, callback: () => callbacks++ });
316+
t.trackPageView();
317+
318+
jest.advanceTimersByTime(100);
319+
t.updatePageActivity();
320+
jest.advanceTimersByTime(4900);
321+
322+
expect(callbacks).toBe(1);
323+
324+
// page ping timer starts tracking
325+
jest.advanceTimersByTime(100);
326+
t.updatePageActivity();
327+
jest.advanceTimersByTime(4900);
328+
329+
expect(callbacks).toBe(2);
330+
331+
/* Disabling activity tracking and callback is expected to not allow more activity actions */
332+
t.disableActivityTracking();
333+
t.disableActivityTrackingCallback();
334+
335+
jest.advanceTimersByTime(100);
336+
t.updatePageActivity();
337+
jest.advanceTimersByTime(4900);
338+
339+
expect(callbacks).toBe(2);
340+
});
278341
});

0 commit comments

Comments
 (0)