@codecademy/tracking 0.25.1-alpha.0c5e25.0 → 0.25.1-alpha.3046e1.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.
@@ -1,4 +1,4 @@
1
- @codecademy/tracking:build: cache hit, replaying output 1d6a7a29a6606c46
1
+ @codecademy/tracking:build: cache hit, replaying output c62a4a09df002c78
2
2
  @codecademy/tracking:build: $ yarn build:clean && yarn build:compile && yarn build:types
3
3
  @codecademy/tracking:build: $ rm -rf dist
4
4
  @codecademy/tracking:build: $ babel ./src --out-dir ./dist --copy-files --extensions ".ts,.tsx"
@@ -7,5 +7,5 @@
7
7
  @codecademy/tracking:build: 
8
8
  @codecademy/tracking:build: Why you should do it regularly:
9
9
  @codecademy/tracking:build: https://github.com/browserslist/browserslist#browsers-data-updating
10
- @codecademy/tracking:build: Successfully compiled 18 files with Babel (2779ms).
10
+ @codecademy/tracking:build: Successfully compiled 20 files with Babel (1936ms).
11
11
  @codecademy/tracking:build: $ tsc --emitDeclarationOnly
package/CHANGELOG.md CHANGED
@@ -3,7 +3,7 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
- ### [0.25.1-alpha.0c5e25.0](https://github.com/Codecademy/client-modules/compare/@codecademy/tracking@0.25.0...@codecademy/tracking@0.25.1-alpha.0c5e25.0) (2022-10-21)
6
+ ### [0.25.1-alpha.3046e1.0](https://github.com/Codecademy/client-modules/compare/@codecademy/tracking@0.25.0...@codecademy/tracking@0.25.1-alpha.3046e1.0) (2022-10-27)
7
7
 
8
8
  **Note:** Version bump only for package @codecademy/tracking
9
9
 
@@ -0,0 +1,58 @@
1
+ import { Consent } from '../consent';
2
+ import { getConsentDecision, OPT_OUT_DATALAYER_VAR } from '../getConsentDecision';
3
+ var MINIMUM_CONSENT = [Consent.StrictlyNecessary];
4
+ var FULL_CONSENT = [Consent.StrictlyNecessary, Consent.Functional, Consent.Performance, Consent.Targeting];
5
+ var FULL_CONSENT_STRING = [','].concat(FULL_CONSENT).join(',');
6
+ describe('getConsentDecision', function () {
7
+ it('converts a stringified consent decision into an array', function () {
8
+ var result = getConsentDecision({
9
+ scope: {
10
+ OnetrustActiveGroups: FULL_CONSENT_STRING
11
+ }
12
+ });
13
+ expect(result).toEqual(FULL_CONSENT);
14
+ });
15
+ it('does not modify an array formatted consent decision', function () {
16
+ var result = getConsentDecision({
17
+ scope: {
18
+ OnetrustActiveGroups: FULL_CONSENT
19
+ }
20
+ });
21
+ expect(result).toEqual(FULL_CONSENT);
22
+ });
23
+ describe('optedOutExternalTracking', function () {
24
+ it('Reduces the consent decision to necessary and functional for opted out users', function () {
25
+ var result = getConsentDecision({
26
+ scope: {
27
+ OnetrustActiveGroups: FULL_CONSENT
28
+ },
29
+ optedOutExternalTracking: true
30
+ });
31
+ expect(result).toEqual([Consent.StrictlyNecessary, Consent.Functional]);
32
+ });
33
+ it('Does not add Functional tracking if the user has opted out of it', function () {
34
+ var result = getConsentDecision({
35
+ scope: {
36
+ OnetrustActiveGroups: MINIMUM_CONSENT
37
+ },
38
+ optedOutExternalTracking: true
39
+ });
40
+ expect(result).toEqual(MINIMUM_CONSENT);
41
+ });
42
+ it('triggers the opt out datalayer variable', function () {
43
+ var _scope$dataLayer;
44
+
45
+ var scope = {
46
+ OnetrustActiveGroups: FULL_CONSENT
47
+ };
48
+ getConsentDecision({
49
+ scope: scope,
50
+ optedOutExternalTracking: true
51
+ });
52
+ var dataLayerVars = (_scope$dataLayer = scope.dataLayer) === null || _scope$dataLayer === void 0 ? void 0 : _scope$dataLayer.map(function (v) {
53
+ return Object.keys(v);
54
+ }).flat();
55
+ expect(dataLayerVars).toEqual([OPT_OUT_DATALAYER_VAR]);
56
+ });
57
+ });
58
+ });
@@ -0,0 +1,8 @@
1
+ import { Consent } from './consent';
2
+ import { TrackingWindow } from './types';
3
+ export interface ConsentDecisionOptions {
4
+ scope: TrackingWindow;
5
+ optedOutExternalTracking?: boolean;
6
+ }
7
+ export declare const OPT_OUT_DATALAYER_VAR = "user_opted_out_external_tracking";
8
+ export declare const getConsentDecision: ({ scope, optedOutExternalTracking, }: ConsentDecisionOptions) => Consent[];
@@ -0,0 +1,32 @@
1
+ function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
2
+
3
+ import { Consent } from './consent';
4
+ export var OPT_OUT_DATALAYER_VAR = 'user_opted_out_external_tracking';
5
+ export var getConsentDecision = function getConsentDecision(_ref) {
6
+ var scope = _ref.scope,
7
+ optedOutExternalTracking = _ref.optedOutExternalTracking;
8
+ var consentDecision = [];
9
+
10
+ if (typeof scope.OnetrustActiveGroups === 'string') {
11
+ consentDecision = scope.OnetrustActiveGroups.split(',').filter(Boolean);
12
+ } else if (scope.OnetrustActiveGroups) {
13
+ consentDecision = scope.OnetrustActiveGroups;
14
+ }
15
+
16
+ if (optedOutExternalTracking) {
17
+ var _scope$dataLayer;
18
+
19
+ /**
20
+ * If user has already opted out of everything but the essentials
21
+ * don't force them to consent to Functional trackers
22
+ */
23
+ if (consentDecision.length > 1) {
24
+ consentDecision = [Consent.StrictlyNecessary, Consent.Functional];
25
+ }
26
+
27
+ (_scope$dataLayer = scope.dataLayer) !== null && _scope$dataLayer !== void 0 ? _scope$dataLayer : scope.dataLayer = [];
28
+ scope.dataLayer.push(_defineProperty({}, OPT_OUT_DATALAYER_VAR, true));
29
+ }
30
+
31
+ return consentDecision;
32
+ };
@@ -16,6 +16,10 @@ export declare type TrackingIntegrationsSettings = {
16
16
  * User details to identify in Segment.
17
17
  */
18
18
  user?: UserIntegrationSummary;
19
+ /**
20
+ * Whether user has opted out or is excluded from external tracking
21
+ */
22
+ optedOutExternalTracking?: boolean;
19
23
  /**
20
24
  * Segment write key.
21
25
  */
@@ -24,4 +28,4 @@ export declare type TrackingIntegrationsSettings = {
24
28
  /**
25
29
  * @see README.md for details and usage.
26
30
  */
27
- export declare const initializeTrackingIntegrations: ({ onError, production, scope, user, writeKey, }: TrackingIntegrationsSettings) => Promise<void>;
31
+ export declare const initializeTrackingIntegrations: ({ onError, production, scope, user, optedOutExternalTracking, writeKey, }: TrackingIntegrationsSettings) => Promise<void>;
@@ -6,6 +6,7 @@ function _asyncToGenerator(fn) { return function () { var self = this, args = ar
6
6
 
7
7
  import { conditionallyLoadAnalytics } from './conditionallyLoadAnalytics';
8
8
  import { fetchDestinationsForWriteKey } from './fetchDestinationsForWriteKey';
9
+ import { getConsentDecision } from './getConsentDecision';
9
10
  import { mapDestinations } from './mapDestinations';
10
11
  import { initializeOneTrust } from './onetrust';
11
12
  import { runSegmentSnippet } from './runSegmentSnippet';
@@ -15,13 +16,13 @@ import { runSegmentSnippet } from './runSegmentSnippet';
15
16
  */
16
17
  export var initializeTrackingIntegrations = /*#__PURE__*/function () {
17
18
  var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee(_ref) {
18
- var onError, production, scope, user, writeKey, destinations, _mapDestinations, destinationPreferences, identifyPreferences;
19
+ var onError, production, scope, user, optedOutExternalTracking, writeKey, destinations, consentDecision, _mapDestinations, destinationPreferences, identifyPreferences;
19
20
 
20
21
  return _regeneratorRuntime.wrap(function _callee$(_context) {
21
22
  while (1) {
22
23
  switch (_context.prev = _context.next) {
23
24
  case 0:
24
- onError = _ref.onError, production = _ref.production, scope = _ref.scope, user = _ref.user, writeKey = _ref.writeKey;
25
+ onError = _ref.onError, production = _ref.production, scope = _ref.scope, user = _ref.user, optedOutExternalTracking = _ref.optedOutExternalTracking, writeKey = _ref.writeKey;
25
26
  _context.next = 3;
26
27
  return new Promise(function (resolve) {
27
28
  return setTimeout(resolve, 1000);
@@ -55,9 +56,13 @@ export var initializeTrackingIntegrations = /*#__PURE__*/function () {
55
56
  return _context.abrupt("return");
56
57
 
57
58
  case 11:
58
- // 5. Those integrations are compared against the user's consent decisions into a list of allowed destinations
59
+ consentDecision = getConsentDecision({
60
+ scope: scope,
61
+ optedOutExternalTracking: optedOutExternalTracking
62
+ }); // 5. Those integrations are compared against the user's consent decisions into a list of allowed destinations
63
+
59
64
  _mapDestinations = mapDestinations({
60
- consentDecision: scope.OnetrustActiveGroups,
65
+ consentDecision: consentDecision,
61
66
  destinations: destinations
62
67
  }), destinationPreferences = _mapDestinations.destinationPreferences, identifyPreferences = _mapDestinations.identifyPreferences; // 6. We load only those allowed destinations using Segment's `analytics.load`
63
68
 
@@ -69,7 +74,7 @@ export var initializeTrackingIntegrations = /*#__PURE__*/function () {
69
74
  writeKey: writeKey
70
75
  });
71
76
 
72
- case 13:
77
+ case 14:
73
78
  case "end":
74
79
  return _context.stop();
75
80
  }
@@ -23,14 +23,13 @@ export var initializeOneTrust = /*#__PURE__*/function () {
23
23
  document.body.appendChild(style);
24
24
  return _context.abrupt("return", new Promise(function (resolve) {
25
25
  scope.OptanonWrapper = function () {
26
- var _scope$dataLayer, _script$parentNode;
26
+ var _scope$dataLayer;
27
27
 
28
28
  (_scope$dataLayer = scope.dataLayer) !== null && _scope$dataLayer !== void 0 ? _scope$dataLayer : scope.dataLayer = [];
29
29
  scope.dataLayer.push({
30
30
  event: 'OneTrustGroupsUpdated'
31
31
  });
32
- resolve();
33
- (_script$parentNode = script.parentNode) === null || _script$parentNode === void 0 ? void 0 : _script$parentNode.removeChild(script);
32
+ resolve(); // script.parentNode?.removeChild(script);
34
33
  };
35
34
  }));
36
35
 
@@ -16,9 +16,14 @@ export interface SegmentDestination {
16
16
  export interface SegmentAnalyticsOptions {
17
17
  integrations: Record<string, boolean>;
18
18
  }
19
+ export interface OneTrustSDK {
20
+ RejectAll: () => void;
21
+ UpdateConsent?: (category: string, code: string) => void;
22
+ }
19
23
  export interface TrackingWindow {
20
24
  analytics?: SegmentAnalytics;
21
25
  dataLayer?: unknown[];
22
- OnetrustActiveGroups?: Consent[];
26
+ OnetrustActiveGroups?: Consent[] | string;
23
27
  OptanonWrapper?: () => void;
28
+ OneTrust?: OneTrustSDK;
24
29
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@codecademy/tracking",
3
3
  "description": "Tracking library for Codecademy apps.",
4
- "version": "0.25.1-alpha.0c5e25.0",
4
+ "version": "0.25.1-alpha.3046e1.0",
5
5
  "author": "Codecademy Engineering <dev@codecademy.com>",
6
6
  "module": "./dist/index.js",
7
7
  "main": "./dist/index.js",
@@ -16,7 +16,7 @@
16
16
  "@babel/cli": "^7.13.10",
17
17
  "@types/fetch-mock": "^7.3.3",
18
18
  "@types/jest": "^26.0.15",
19
- "babel-preset-codecademy": "6.0.1-alpha.0c5e25.0",
19
+ "babel-preset-codecademy": "^6.0.0",
20
20
  "fetch-mock": "^9.11.0",
21
21
  "jest-fetch-mock": "^3.0.3",
22
22
  "ts-jest": "^26.4.1",
@@ -35,5 +35,5 @@
35
35
  "publishConfig": {
36
36
  "access": "public"
37
37
  },
38
- "gitHead": "c14cd6faf9b1146fb3476c090a8f73b82c16f79d"
38
+ "gitHead": "5c3251be3d89b64ce890153c3783c04b4d50c8e0"
39
39
  }