Skip to content

Commit f1b3365

Browse files
Jack-Keeneigneel64
authored andcommitted
Introduce Enhanced Consent Plugin
1 parent 8ac090d commit f1b3365

22 files changed

+694
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@snowplow/browser-plugin-enhanced-consent",
5+
"comment": "",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@snowplow/browser-plugin-enhanced-consent"
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@snowplow/browser-plugin-enhanced-consent",
5+
"comment": "",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@snowplow/browser-plugin-enhanced-consent"
10+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@snowplow/javascript-tracker",
5+
"comment": "",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@snowplow/javascript-tracker"
10+
}

common/config/rush/browser-approved-packages.json

+4
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@
6666
"name": "@snowplow/browser-plugin-ecommerce",
6767
"allowedCategories": [ "trackers" ]
6868
},
69+
{
70+
"name": "@snowplow/browser-plugin-enhanced-consent",
71+
"allowedCategories": [ "trackers" ]
72+
},
6973
{
7074
"name": "@snowplow/browser-plugin-enhanced-ecommerce",
7175
"allowedCategories": [ "trackers" ]

common/config/rush/pnpm-lock.yaml

+55
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

common/config/rush/repo-state.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush.
22
{
3-
"pnpmShrinkwrapHash": "7a34ebb96f6d1ef2f72d510e51232937cbbc88c2",
3+
"pnpmShrinkwrapHash": "a89befd25d9043396ee1a3dda2def22a80582f46",
44
"preferredVersionsHash": "bf21a9e8fbc5a3846fb05b4fa0859e0917b2202f"
55
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
preset: 'ts-jest',
3+
reporters: ['jest-standard-reporter'],
4+
testEnvironment: 'jest-environment-jsdom-global',
5+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
{
2+
"name": "@snowplow/browser-plugin-enhanced-consent",
3+
"version": "3.7.0",
4+
"description": "Consent tracking for Snowplow",
5+
"bugs": "https://github.com/snowplow/snowplow-javascript-tracker/issues",
6+
"repository": {
7+
"type": "git",
8+
"url": "https://github.com/snowplow/snowplow-javascript-tracker.git"
9+
},
10+
"license": "BSD-3-Clause",
11+
"author": "Jack Keene",
12+
"sideEffects": false,
13+
"main": "./dist/index.umd.js",
14+
"module": "./dist/index.module.js",
15+
"types": "./dist/index.module.d.ts",
16+
"files": [
17+
"dist"
18+
],
19+
"scripts": {
20+
"build": "rollup -c --silent --failAfterWarnings",
21+
"test": "jest"
22+
},
23+
"dependencies": {
24+
"@snowplow/browser-tracker-core": "workspace:*",
25+
"@snowplow/tracker-core": "workspace:*",
26+
"tslib": "^2.3.1"
27+
},
28+
"devDependencies": {
29+
"@ampproject/rollup-plugin-closure-compiler": "~0.27.0",
30+
"@rollup/plugin-commonjs": "~21.0.2",
31+
"@rollup/plugin-node-resolve": "~13.1.3",
32+
"@types/jest": "~27.4.1",
33+
"@types/jsdom": "~16.2.14",
34+
"@types/lodash": "~4.14.180",
35+
"@typescript-eslint/eslint-plugin": "~5.15.0",
36+
"@typescript-eslint/parser": "~5.15.0",
37+
"eslint": "~8.11.0",
38+
"jest": "~27.5.1",
39+
"jest-environment-jsdom": "~27.5.1",
40+
"jest-environment-jsdom-global": "~3.0.0",
41+
"jest-standard-reporter": "~2.0.0",
42+
"lodash": "~4.17.21",
43+
"rollup": "~2.70.1",
44+
"rollup-plugin-cleanup": "~3.2.1",
45+
"rollup-plugin-license": "~2.6.1",
46+
"rollup-plugin-terser": "~7.0.2",
47+
"rollup-plugin-ts": "~2.0.5",
48+
"ts-jest": "~27.1.3",
49+
"typescript": "~4.6.2"
50+
},
51+
"peerDependencies": {
52+
"@snowplow/browser-tracker": "~3.5.0"
53+
}
54+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright (c) 2022 Snowplow Analytics Ltd, 2010 Anthon Pang
3+
* All rights reserved.
4+
*
5+
* Redistribution and use in source and binary forms, with or without
6+
* modification, are permitted provided that the following conditions are met:
7+
*
8+
* 1. Redistributions of source code must retain the above copyright notice, this
9+
* list of conditions and the following disclaimer.
10+
*
11+
* 2. Redistributions in binary form must reproduce the above copyright notice,
12+
* this list of conditions and the following disclaimer in the documentation
13+
* and/or other materials provided with the distribution.
14+
*
15+
* 3. Neither the name of the copyright holder nor the names of its
16+
* contributors may be used to endorse or promote products derived from
17+
* this software without specific prior written permission.
18+
*
19+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22+
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28+
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29+
*/
30+
31+
import { nodeResolve } from '@rollup/plugin-node-resolve';
32+
import commonjs from '@rollup/plugin-commonjs';
33+
import ts from 'rollup-plugin-ts'; // Prefered over @rollup/plugin-typescript as it bundles .d.ts files
34+
import { banner } from '../../banner';
35+
import compiler from '@ampproject/rollup-plugin-closure-compiler';
36+
import { terser } from 'rollup-plugin-terser';
37+
import cleanup from 'rollup-plugin-cleanup';
38+
import pkg from './package.json';
39+
import { builtinModules } from 'module';
40+
41+
const umdPlugins = [nodeResolve({ browser: true }), commonjs(), ts()];
42+
const umdName = 'snowplowEnhancedConsentTracking';
43+
44+
export default [
45+
// CommonJS (for Node) and ES module (for bundlers) build.
46+
{
47+
input: './src/index.ts',
48+
plugins: [...umdPlugins, banner()],
49+
treeshake: { moduleSideEffects: ['sha1'] },
50+
output: [{ file: pkg.main, format: 'umd', sourcemap: true, name: umdName }],
51+
},
52+
{
53+
input: './src/index.ts',
54+
plugins: [...umdPlugins, compiler(), terser(), cleanup({ comments: 'none' }), banner()],
55+
treeshake: { moduleSideEffects: ['sha1'] },
56+
output: [{ file: pkg.main.replace('.js', '.min.js'), format: 'umd', sourcemap: true, name: umdName }],
57+
},
58+
{
59+
input: './src/index.ts',
60+
external: [...builtinModules, ...Object.keys(pkg.dependencies), ...Object.keys(pkg.devDependencies)],
61+
plugins: [
62+
ts(), // so Rollup can convert TypeScript to JavaScript
63+
banner(),
64+
],
65+
output: [{ file: pkg.module, format: 'es', sourcemap: true }],
66+
},
67+
];
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
import { BrowserPlugin, BrowserTracker, dispatchToTrackersInCollection } from '@snowplow/browser-tracker-core';
2+
import { buildConsentEvent, buildCmpVisibleEvent } from './core';
3+
import { CommonConsentEventProperties, Consent, CmpVisible } from './types';
4+
5+
const _trackers: Record<string, BrowserTracker> = {};
6+
7+
type ConsentEventProperties = Omit<Consent, 'eventType'> & CommonConsentEventProperties;
8+
9+
/**
10+
* Adds consent tracking
11+
*/
12+
13+
export function EnhancedConsentPlugin(): BrowserPlugin {
14+
let trackerId: string;
15+
return {
16+
activateBrowserPlugin: (tracker) => {
17+
trackerId = tracker.id;
18+
_trackers[trackerId] = tracker;
19+
},
20+
};
21+
}
22+
23+
/**
24+
* Track the loadtime of a CMP banner
25+
*/
26+
27+
export function trackCmpVisible(
28+
cmpVisible: CmpVisible & CommonConsentEventProperties,
29+
trackers: Array<string> = Object.keys(_trackers)
30+
) {
31+
const { context, timestamp, elapsedTime } = cmpVisible;
32+
dispatchToTrackersInCollection(trackers, _trackers, (t) => {
33+
t.core.track(
34+
buildCmpVisibleEvent({
35+
elapsedTime,
36+
}),
37+
context,
38+
timestamp
39+
);
40+
});
41+
}
42+
43+
// Generic consent action
44+
function trackConsentAction(
45+
consent: Consent & CommonConsentEventProperties,
46+
trackers: Array<string> = Object.keys(_trackers)
47+
) {
48+
const { context, timestamp, ...consentAttributes } = consent;
49+
dispatchToTrackersInCollection(trackers, _trackers, (t) => {
50+
t.core.track(buildConsentEvent(consentAttributes), context, timestamp);
51+
});
52+
}
53+
54+
/**
55+
* Track an allow consent event
56+
*
57+
* @param consent - The consent information
58+
* @param trackers - The tracker identifiers which the event will be sent to
59+
*/
60+
61+
export function trackConsentAllow(consent: ConsentEventProperties, trackers: Array<string> = Object.keys(_trackers)) {
62+
trackConsentAction({ ...consent, eventType: 'allow_all' }, trackers);
63+
}
64+
65+
/**
66+
* Track an allow selected consent event
67+
*
68+
* @param consent - The consent information
69+
* @param trackers - The tracker identifiers which the event will be sent to
70+
*/
71+
72+
export function trackConsentSelected(
73+
consent: ConsentEventProperties,
74+
trackers: Array<string> = Object.keys(_trackers)
75+
) {
76+
trackConsentAction({ ...consent, eventType: 'allow_selected' }, trackers);
77+
}
78+
79+
/**
80+
* Track a consent pending event
81+
*
82+
* @param consent - The consent information
83+
* @param trackers - The tracker identifiers which the event will be sent to
84+
*/
85+
86+
export function trackConsentPending(consent: ConsentEventProperties, trackers: Array<string> = Object.keys(_trackers)) {
87+
trackConsentAction({ ...consent, eventType: 'pending' }, trackers);
88+
}
89+
90+
/**
91+
* Track an implicit consent event
92+
*
93+
* @param consent - The consent information
94+
* @param trackers - The tracker identifiers which the event will be sent to
95+
*/
96+
97+
export function trackConsentImplicit(
98+
consent: ConsentEventProperties,
99+
trackers: Array<string> = Object.keys(_trackers)
100+
) {
101+
trackConsentAction({ ...consent, eventType: 'implicit_consent' }, trackers);
102+
}
103+
104+
/**
105+
* Track a deny consent event
106+
*
107+
* @param consent - The consent information
108+
* @param trackers - The tracker identifiers which the event will be sent to
109+
*/
110+
111+
export function trackConsentDeny(consent: ConsentEventProperties, trackers: Array<string> = Object.keys(_trackers)) {
112+
trackConsentAction({ ...consent, eventType: 'deny_all' }, trackers);
113+
}
114+
115+
/**
116+
* Track a consent expired event
117+
*
118+
* @param consent - The consent information
119+
* @param trackers - The tracker identifiers which the event will be sent to
120+
*/
121+
122+
export function trackConsentExpired(consent: ConsentEventProperties, trackers: Array<string> = Object.keys(_trackers)) {
123+
trackConsentAction({ ...consent, eventType: 'expired' }, trackers);
124+
}
125+
126+
/**
127+
* Track a consent withdrawn event
128+
*
129+
* @param consent - The consent information
130+
* @param trackers - The tracker identifiers which the event will be sent to
131+
*/
132+
133+
export function trackConsentWithdrawn(
134+
consent: ConsentEventProperties,
135+
trackers: Array<string> = Object.keys(_trackers)
136+
) {
137+
trackConsentAction({ ...consent, eventType: 'withdrawn' }, trackers);
138+
}

0 commit comments

Comments
 (0)