@codecademy/tracking 1.0.36-alpha.fcc420c4e3.0 → 1.0.36

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.
@@ -3,7 +3,7 @@ export type GTMSettings = {
3
3
  environment: string;
4
4
  scope: TrackingWindow;
5
5
  optedOutExternalTracking?: boolean;
6
- partytown?: boolean;
6
+ enablePartytown?: boolean;
7
7
  };
8
8
  export declare const OPT_OUT_DATALAYER_VAR = "user_opted_out_external_tracking";
9
- export declare const initializeGTM: ({ scope, environment, optedOutExternalTracking, partytown, }: GTMSettings) => void;
9
+ export declare const initializeGTM: ({ scope, environment, optedOutExternalTracking, enablePartytown, }: GTMSettings) => void;
@@ -3,7 +3,7 @@ export const initializeGTM = _ref => {
3
3
  let scope = _ref.scope,
4
4
  environment = _ref.environment,
5
5
  optedOutExternalTracking = _ref.optedOutExternalTracking,
6
- partytown = _ref.partytown;
6
+ enablePartytown = _ref.enablePartytown;
7
7
  scope.dataLayer ??= [];
8
8
  scope.dataLayer.push({
9
9
  'gtm.start': new Date().getTime(),
@@ -22,13 +22,14 @@ export const initializeGTM = _ref => {
22
22
  }
23
23
  const gtm = document.createElement('script');
24
24
  gtm.src = `https://www.googletagmanager.com/gtm.js?id=GTM-KTLK85W${preview_env}`;
25
- if (partytown) {
25
+ if (enablePartytown) {
26
26
  gtm.type = 'text/partytown';
27
27
  } else {
28
28
  gtm.async = true;
29
29
  }
30
30
  document.getElementsByTagName('head')[0].appendChild(gtm);
31
- if (partytown) {
31
+ if (enablePartytown) {
32
+ // Let Partytown know that a new script has been added.
32
33
  window.dispatchEvent(new CustomEvent('ptupdate'));
33
34
  }
34
35
  };
@@ -17,12 +17,11 @@ export type TrackingIntegrationsSettings = {
17
17
  */
18
18
  oneTrustScript?: string;
19
19
  /**
20
- * Use partytown to load scripts.
21
- * next.config.js experimental: { nextScriptWorkers } must be set to true.
20
+ * Use Partytown to load 3rd party scripts in a worker.
22
21
  */
23
- partytown?: boolean;
22
+ enablePartytown?: boolean;
24
23
  };
25
24
  /**
26
25
  * @see README.md for details and usage.
27
26
  */
28
- export declare const initializeTrackingIntegrations: ({ environment, scope, optedOutExternalTracking, oneTrustScript, partytown, }: TrackingIntegrationsSettings) => Promise<void>;
27
+ export declare const initializeTrackingIntegrations: ({ environment, scope, optedOutExternalTracking, oneTrustScript, enablePartytown, }: TrackingIntegrationsSettings) => Promise<void>;
@@ -1,7 +1,7 @@
1
1
  import { initializeGTM } from './gtm';
2
2
  import { initializeOneTrust } from './onetrust';
3
3
  import { initializePartytown } from './partytown';
4
- let init = false; // For preventing multiple initializations
4
+ let init = false;
5
5
 
6
6
  /**
7
7
  * @see README.md for details and usage.
@@ -11,12 +11,10 @@ export const initializeTrackingIntegrations = async _ref => {
11
11
  scope = _ref.scope,
12
12
  optedOutExternalTracking = _ref.optedOutExternalTracking,
13
13
  oneTrustScript = _ref.oneTrustScript,
14
- partytown = _ref.partytown;
15
- if (init) {
16
- return;
17
- }
14
+ enablePartytown = _ref.enablePartytown;
15
+ if (init) return; // Prevent multiple initializations
18
16
  init = true;
19
- if (partytown) {
17
+ if (enablePartytown) {
20
18
  initializePartytown();
21
19
  } else {
22
20
  // Wait to allow any other post-hydration logic to run first
@@ -35,6 +33,6 @@ export const initializeTrackingIntegrations = async _ref => {
35
33
  scope,
36
34
  environment,
37
35
  optedOutExternalTracking,
38
- partytown
36
+ enablePartytown
39
37
  });
40
38
  };
@@ -0,0 +1,2 @@
1
+ import { PartytownConfig } from '@builder.io/partytown/integration';
2
+ export declare const partytownConfig: () => PartytownConfig;
@@ -0,0 +1,36 @@
1
+ export const partytownConfig = () => ({
2
+ forward: ['dataLayer.push',
3
+ // for GTM
4
+ 'fbq',
5
+ // for Facebook Pixel
6
+ '_hsq.push' // for Hubspot
7
+ ],
8
+ lib: '/partytown/',
9
+ // path for loading from static asset CMS
10
+ loadScriptsOnMainThread: [/googleads/,
11
+ // Google Ads
12
+ /bing/,
13
+ // Bing UET
14
+ /pepperjam/,
15
+ // Pepperjam
16
+ /snap/,
17
+ // Snap Pixel
18
+ /lightboxcdn/ // Digioh
19
+ ],
20
+ // This function runs in a worker and can't access other vars in this file.
21
+ resolveUrl(url, location, type) {
22
+ // Block GTM from trying to add its own service worker via iframe.
23
+ if (url.hostname === 'www.googletagmanager.com' && type === 'iframe') {
24
+ return new URL('', 'https:.');
25
+ }
26
+
27
+ /*
28
+ * Proxy Facebook Pixel requests to resolve CORS issues
29
+ * see https://partytown.builder.io/facebook-pixel#proxy-requests
30
+ */
31
+ if (url.hostname === 'connect.facebook.net') {
32
+ return new URL(`partytown-fb${url.pathname}${url.search}`, location.origin);
33
+ }
34
+ return url;
35
+ }
36
+ });
@@ -0,0 +1,10 @@
1
+ import { partytownSnippet } from '@builder.io/partytown/integration';
2
+ import { partytownConfig } from './config';
3
+
4
+ // Encapsulate to avoid collision of global vars aliased in minification.
5
+ const encapsulate = js => `(() => {${js}})();`;
6
+ export function initializePartytown() {
7
+ const ptScript = document.createElement('script');
8
+ ptScript.innerHTML = encapsulate(partytownSnippet(partytownConfig()));
9
+ document.head.appendChild(ptScript);
10
+ }
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "@codecademy/tracking",
3
3
  "description": "Tracking library for Codecademy",
4
- "version": "1.0.36-alpha.fcc420c4e3.0",
4
+ "version": "1.0.36",
5
5
  "author": "Codecademy Engineering <dev@codecademy.com>",
6
+ "dependencies": {
7
+ "@builder.io/partytown": "^0.10.2"
8
+ },
6
9
  "files": [
7
10
  "dist/**"
8
11
  ],
@@ -13,5 +16,5 @@
13
16
  "access": "public"
14
17
  },
15
18
  "repository": "git@github.com:codecademy-engineering/mono.git",
16
- "gitHead": "4c4b9f0e464b24a3e5aa4c17cde7437e3c2424e9"
19
+ "gitHead": "5eef9730521dc255c8d8260a9c25978a20e06e68"
17
20
  }
@@ -1,66 +0,0 @@
1
- import { partytownSnippet } from '@builder.io/partytown/integration';
2
- const ptConfig = () => ({
3
- forward: [['dataLayer.push', {
4
- preserveBehavior: true
5
- }], ['fbq', {
6
- preserveBehavior: true
7
- }]],
8
- lib: '/partytown/',
9
- logScriptExecution: true,
10
- loadScriptsOnMainThread: [/googleads/, /bing/, /pepperjam/, /facebook/, /snap/, /lightboxcdn/],
11
- resolveUrl(url, _, type) {
12
- /*
13
- * This function runs in a worker and cannot access vars that might seem
14
- * in scope in this file.
15
- */
16
-
17
- /*
18
- * GTM tries to create an iframe that loads a script to create a GTM
19
- * service worker. When scripts within Partytown try to create an iframe,
20
- * Partytown's proxy behavior is to make the request for the iframe src
21
- * using fetch from a worker. This is typically better than normal iframe
22
- * loading behavior because it keeps the request off the main thread.
23
- * However, fetch in a worker is more strict about cors than requests
24
- * natively made by iframe elements. A fetch for this particular iframe
25
- * src would fail becuase Google does not include a cors response header.
26
- * In some cases with Partytown, we might work around this with a reverse
27
- * proxy, but that also doesn't work in this case because the GTM code in
28
- * this iframe needs to create a service worker within an iframe that has
29
- * a certain origin. The alternate workaround here is to effectively
30
- * block Partytown when it tries to resolve the iframe url and to send
31
- * that url back to the main thread (via BroadcastChannel) so that a
32
- * regular iframe can be created, just as GTM would have normally done.
33
- */
34
- if (url.hostname === 'www.googletagmanager.com' && type === 'iframe') {
35
- new BroadcastChannel('gtm-iframe').postMessage(url.href);
36
- return new URL('', 'http:.');
37
- }
38
- return url;
39
- }
40
- });
41
- const encapsulate = js => `(() => {${js}})();`;
42
- export function initializePartytown() {
43
- new BroadcastChannel('gtm-iframe').onmessage = _ref => {
44
- let iframeSrc = _ref.data;
45
- // This 2 layer approach matches the way GTM would try to setup the iframe.
46
- const outer = hiddenIframe(document);
47
- document.body.appendChild(outer);
48
- const inner = hiddenIframe(outer.contentWindow.document, iframeSrc);
49
- outer.appendChild(inner);
50
- };
51
- const ptScript = document.createElement('script');
52
- // encapsulation is necessary to avoid collision of global minified vars
53
- ptScript.innerHTML = encapsulate(partytownSnippet(ptConfig()));
54
- document.head.appendChild(ptScript);
55
- }
56
- function hiddenIframe(d, src) {
57
- const iframe = d.createElement('iframe');
58
- // These attributes match what GTM would use when it creates an iframe.
59
- iframe.height = '0';
60
- iframe.width = '0';
61
- iframe.setAttribute('style', 'display: none; visibility: hidden;');
62
- if (src) {
63
- iframe.src = src;
64
- }
65
- return iframe;
66
- }