saasco-sdk 0.1.27 → 0.1.30
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.
- package/README.md +1 -1
- package/index.cjs.js +89 -72
- package/index.esm.js +90 -71
- package/package.json +1 -1
- package/src/index.d.ts +0 -1
- package/src/lib/tracking/types.d.ts +31 -20
- package/src/lib/getUTMContext.d.ts +0 -2
package/README.md
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
## 🔒 Privacy
|
|
16
16
|
|
|
17
|
-
By default Saasco is privacy friendly,
|
|
17
|
+
By default Saasco is privacy friendly, obscuring all activity behind Anonymous IDs. However if you want to power more complex user tracking you can identify users and then all events they do will be attributed to them in your CRM. This can assist with customer support but also for things like drip campaigns and other marketing activities.
|
|
18
18
|
|
|
19
19
|
## Getting Started
|
|
20
20
|
|
package/index.cjs.js
CHANGED
|
@@ -7,7 +7,7 @@ var uuid = require('@lukeed/uuid');
|
|
|
7
7
|
var psl = require('psl');
|
|
8
8
|
var zod = require('zod');
|
|
9
9
|
|
|
10
|
-
var version = "0.1.
|
|
10
|
+
var version = "0.1.30";
|
|
11
11
|
|
|
12
12
|
const timezones = {
|
|
13
13
|
'Asia/Barnaul': 'RU',
|
|
@@ -455,6 +455,17 @@ function getBrowserContext() {
|
|
|
455
455
|
const $screenWidth = screen.width;
|
|
456
456
|
const $title = document.title;
|
|
457
457
|
const $userAgent = window.navigator.userAgent;
|
|
458
|
+
const params = new URLSearchParams(window.location.search);
|
|
459
|
+
const $utmSource = params.get('utm_source');
|
|
460
|
+
const $utmMedium = params.get('utm_medium');
|
|
461
|
+
const $utmCampaign = params.get('utm_campaign');
|
|
462
|
+
const $utmTerm = params.get('utm_term');
|
|
463
|
+
const $utmContent = params.get('utm_content');
|
|
464
|
+
const $utmId = params.get('utm_id');
|
|
465
|
+
const $utmSourcePlatform = params.get('utm_source_platform');
|
|
466
|
+
const $utmCampaignId = params.get('utm_campaign_id');
|
|
467
|
+
const $utmCreativeFormat = params.get('utm_creative_format');
|
|
468
|
+
const $utmMarketingTactic = params.get('utm_marketing_tactic');
|
|
458
469
|
return {
|
|
459
470
|
$locale,
|
|
460
471
|
$location,
|
|
@@ -465,55 +476,43 @@ function getBrowserContext() {
|
|
|
465
476
|
$screenHeight,
|
|
466
477
|
$screenWidth,
|
|
467
478
|
$title,
|
|
468
|
-
$userAgent
|
|
479
|
+
$userAgent,
|
|
480
|
+
$utmSource,
|
|
481
|
+
$utmMedium,
|
|
482
|
+
$utmCampaign,
|
|
483
|
+
$utmTerm,
|
|
484
|
+
$utmContent,
|
|
485
|
+
$utmId,
|
|
486
|
+
$utmSourcePlatform,
|
|
487
|
+
$utmCampaignId,
|
|
488
|
+
$utmCreativeFormat,
|
|
489
|
+
$utmMarketingTactic
|
|
469
490
|
};
|
|
470
491
|
}
|
|
471
492
|
|
|
472
|
-
function getUTMContext() {
|
|
473
|
-
const isBrowser = typeof window !== 'undefined';
|
|
474
|
-
if (!isBrowser) throw new Error('getUTMContext can only be called in browser');
|
|
475
|
-
const params = new URLSearchParams(window.location.search);
|
|
476
|
-
const $utmSource = params.get('utm_source');
|
|
477
|
-
const $utmMedium = params.get('utm_medium');
|
|
478
|
-
const $utmCampaign = params.get('utm_campaign');
|
|
479
|
-
const $utmTerm = params.get('utm_term');
|
|
480
|
-
const $utmContent = params.get('utm_content');
|
|
481
|
-
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, $utmSource ? {
|
|
482
|
-
$utmSource
|
|
483
|
-
} : {}), $utmMedium ? {
|
|
484
|
-
$utmMedium
|
|
485
|
-
} : {}), $utmCampaign ? {
|
|
486
|
-
$utmCampaign
|
|
487
|
-
} : {}), $utmTerm ? {
|
|
488
|
-
$utmTerm
|
|
489
|
-
} : {}), $utmContent ? {
|
|
490
|
-
$utmContent
|
|
491
|
-
} : {});
|
|
492
|
-
}
|
|
493
|
-
|
|
494
493
|
const isBrowser = typeof window !== 'undefined';
|
|
495
494
|
const isServer = !isBrowser;
|
|
496
495
|
const PREF = 'saasco-sdk';
|
|
497
496
|
const SESSION_DURATION = 1000 * 60 * 30;
|
|
498
497
|
const USER_DURATION = 1000 * 60 * 60 * 24 * 365;
|
|
499
498
|
const data = {};
|
|
500
|
-
function getRootDomain() {
|
|
499
|
+
function getRootDomain(url) {
|
|
501
500
|
if (isServer) return;
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
return
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
501
|
+
if (!url) return;
|
|
502
|
+
try {
|
|
503
|
+
const hostname = new URL(url).hostname;
|
|
504
|
+
if (!psl.isValid(hostname)) return;
|
|
505
|
+
const parsed = psl.parse(hostname);
|
|
506
|
+
if ('domain' in parsed && parsed.domain) return parsed.domain;
|
|
507
|
+
} catch (error) {
|
|
508
|
+
// invalid url
|
|
510
509
|
}
|
|
511
|
-
return
|
|
510
|
+
return;
|
|
512
511
|
}
|
|
513
512
|
function setCookie(name, value, ttl) {
|
|
514
513
|
if (isServer) return;
|
|
515
514
|
const expires = new Date(Date.now() + ttl).toUTCString();
|
|
516
|
-
const domain = getRootDomain();
|
|
515
|
+
const domain = getRootDomain(window.location.href);
|
|
517
516
|
const cookieString = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/${domain ? `; domain=.${domain}` : ''}`;
|
|
518
517
|
document.cookie = cookieString;
|
|
519
518
|
}
|
|
@@ -532,13 +531,13 @@ function getCookie(name) {
|
|
|
532
531
|
}
|
|
533
532
|
function deleteCookie(name) {
|
|
534
533
|
if (isServer) return;
|
|
535
|
-
const domain = getRootDomain();
|
|
534
|
+
const domain = getRootDomain(window.location.href);
|
|
536
535
|
const cookieString = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/${domain ? `; domain=.${domain}` : ''}`;
|
|
537
536
|
document.cookie = cookieString;
|
|
538
537
|
}
|
|
539
538
|
function migrateFromLocalStorage() {
|
|
540
539
|
if (isServer) return;
|
|
541
|
-
const keysToMigrate = [`${PREF}-session-id`, `${PREF}-anonymous-id`, `${PREF}-user-id`, `${PREF}-session-utm-context`];
|
|
540
|
+
const keysToMigrate = [`${PREF}-session-id`, `${PREF}-anonymous-id`, `${PREF}-user-id`, `${PREF}-session-utm-context`, `${PREF}-super-context`];
|
|
542
541
|
keysToMigrate.forEach(key => {
|
|
543
542
|
try {
|
|
544
543
|
const value = localStorage.getItem(key);
|
|
@@ -583,7 +582,11 @@ function storeData(key, value, ttl) {
|
|
|
583
582
|
deleteCookie(fullKey);
|
|
584
583
|
return;
|
|
585
584
|
}
|
|
586
|
-
|
|
585
|
+
const item = {
|
|
586
|
+
value,
|
|
587
|
+
expiry: new Date().getTime() + ttl
|
|
588
|
+
};
|
|
589
|
+
setCookie(fullKey, JSON.stringify(item), ttl);
|
|
587
590
|
}
|
|
588
591
|
function retrieveData(key) {
|
|
589
592
|
if (isServer) {
|
|
@@ -601,7 +604,12 @@ function retrieveData(key) {
|
|
|
601
604
|
return null;
|
|
602
605
|
}
|
|
603
606
|
try {
|
|
604
|
-
|
|
607
|
+
const item = JSON.parse(itemStr);
|
|
608
|
+
if (Date.now() > item.expiry) {
|
|
609
|
+
deleteCookie(fullKey);
|
|
610
|
+
return null;
|
|
611
|
+
}
|
|
612
|
+
return item.value;
|
|
605
613
|
} catch (error) {
|
|
606
614
|
// If JSON parsing fails, remove the corrupted cookie
|
|
607
615
|
deleteCookie(fullKey);
|
|
@@ -637,22 +645,31 @@ function getUserId() {
|
|
|
637
645
|
function setUserId(userId) {
|
|
638
646
|
storeData(`user-id`, userId, USER_DURATION);
|
|
639
647
|
}
|
|
640
|
-
function
|
|
641
|
-
return retrieveData(
|
|
648
|
+
function getSuperContext() {
|
|
649
|
+
return retrieveData('super-context') || {};
|
|
642
650
|
}
|
|
643
|
-
function
|
|
644
|
-
storeData(
|
|
651
|
+
function setSuperContext(superContext) {
|
|
652
|
+
storeData('super-context', superContext, SESSION_DURATION);
|
|
645
653
|
}
|
|
646
|
-
function
|
|
647
|
-
|
|
648
|
-
const
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
654
|
+
function updateSuperContext(browserContext) {
|
|
655
|
+
const existingSuperContext = getSuperContext();
|
|
656
|
+
const defaultSuperContextKeys = ['$utmSource', '$utmMedium', '$utmCampaign', '$utmTerm', '$utmContent', '$utmId', '$utmSourcePlatform', '$utmCampaignId', '$utmCreativeFormat', '$utmMarketingTactic'];
|
|
657
|
+
const superContext = defaultSuperContextKeys.reduce((acc, key) => {
|
|
658
|
+
const value = Object.assign({}, browserContext)[key];
|
|
659
|
+
if (value) acc[key] = value;
|
|
660
|
+
return acc;
|
|
661
|
+
}, existingSuperContext);
|
|
662
|
+
// Only set referrer if it's from a different root domain
|
|
663
|
+
// Prevents setting referrer when going between subdomains of the same root domain
|
|
664
|
+
if (browserContext.$referrer) {
|
|
665
|
+
const referrerRootDomain = getRootDomain(browserContext.$referrer);
|
|
666
|
+
const currentRootDomain = getRootDomain(browserContext.$href);
|
|
667
|
+
if (referrerRootDomain && currentRootDomain && referrerRootDomain !== currentRootDomain) {
|
|
668
|
+
superContext['$referrer'] = browserContext.$referrer;
|
|
669
|
+
}
|
|
653
670
|
}
|
|
654
|
-
|
|
655
|
-
return
|
|
671
|
+
setSuperContext(superContext);
|
|
672
|
+
return superContext;
|
|
656
673
|
}
|
|
657
674
|
class Saasco {
|
|
658
675
|
/**
|
|
@@ -733,15 +750,16 @@ class Saasco {
|
|
|
733
750
|
const sessionId = (hasAction ? undefined : actionOrPayload.sessionId) || getSessionId();
|
|
734
751
|
const anonymousId = (hasAction ? undefined : actionOrPayload.anonymousId) || getAnonymousId();
|
|
735
752
|
const distinctId = (hasAction ? undefined : actionOrPayload.userId) || getUserId();
|
|
736
|
-
// Only gets browser and
|
|
753
|
+
// Only gets browser and super context if in the browser
|
|
737
754
|
let browserContext;
|
|
738
|
-
let
|
|
755
|
+
let superContext;
|
|
739
756
|
if (isBrowser) {
|
|
740
757
|
browserContext = getBrowserContext();
|
|
741
|
-
|
|
742
|
-
const sessionUTMContext = handleSessionUTMContext();
|
|
743
|
-
if (sessionUTMContext) utmContext = sessionUTMContext;
|
|
758
|
+
superContext = updateSuperContext(browserContext);
|
|
744
759
|
}
|
|
760
|
+
const payloadJSON = Object.assign(Object.assign(Object.assign({}, browserContext), superContext), {
|
|
761
|
+
properties: properties || {}
|
|
762
|
+
});
|
|
745
763
|
const data = {
|
|
746
764
|
id: uuid.v4(),
|
|
747
765
|
timestamp: new Date().toISOString(),
|
|
@@ -751,9 +769,7 @@ class Saasco {
|
|
|
751
769
|
anonymousId,
|
|
752
770
|
distinctId,
|
|
753
771
|
projectId: this.config.projectId,
|
|
754
|
-
payload: JSON.stringify(
|
|
755
|
-
properties: properties || {}
|
|
756
|
-
})),
|
|
772
|
+
payload: JSON.stringify(payloadJSON),
|
|
757
773
|
source: isBrowser ? 'client' : 'server',
|
|
758
774
|
context: JSON.stringify(context || {})
|
|
759
775
|
};
|
|
@@ -834,8 +850,8 @@ class Saasco {
|
|
|
834
850
|
*
|
|
835
851
|
*/
|
|
836
852
|
logout() {
|
|
837
|
-
// Clear
|
|
838
|
-
|
|
853
|
+
// Clear super context data on logout
|
|
854
|
+
setSuperContext(null);
|
|
839
855
|
this.identify(null);
|
|
840
856
|
}
|
|
841
857
|
/**
|
|
@@ -959,19 +975,20 @@ const browserContextSchema = zod.z.object({
|
|
|
959
975
|
$screenHeight: zod.z.number(),
|
|
960
976
|
$screenWidth: zod.z.number(),
|
|
961
977
|
$title: zod.z.string(),
|
|
962
|
-
$userAgent: zod.z.string()
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
$
|
|
966
|
-
$
|
|
967
|
-
$
|
|
968
|
-
$
|
|
969
|
-
$
|
|
978
|
+
$userAgent: zod.z.string(),
|
|
979
|
+
$utmSource: zod.z.string().nullable(),
|
|
980
|
+
$utmMedium: zod.z.string().nullable(),
|
|
981
|
+
$utmCampaign: zod.z.string().nullable(),
|
|
982
|
+
$utmTerm: zod.z.string().nullable(),
|
|
983
|
+
$utmContent: zod.z.string().nullable(),
|
|
984
|
+
$utmId: zod.z.string().nullable(),
|
|
985
|
+
$utmSourcePlatform: zod.z.string().nullable(),
|
|
986
|
+
$utmCampaignId: zod.z.string().nullable(),
|
|
987
|
+
$utmCreativeFormat: zod.z.string().nullable(),
|
|
988
|
+
$utmMarketingTactic: zod.z.string().nullable()
|
|
970
989
|
});
|
|
971
990
|
|
|
972
991
|
exports.Saasco = Saasco;
|
|
973
992
|
exports.browserContextSchema = browserContextSchema;
|
|
974
993
|
exports.getBrowserContext = getBrowserContext;
|
|
975
|
-
exports.getUTMContext = getUTMContext;
|
|
976
994
|
exports.timezones = timezones;
|
|
977
|
-
exports.utmContextSchema = utmContextSchema;
|
package/index.esm.js
CHANGED
|
@@ -3,7 +3,7 @@ import { v4 } from '@lukeed/uuid';
|
|
|
3
3
|
import { isValid, parse } from 'psl';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
|
|
6
|
-
var version = "0.1.
|
|
6
|
+
var version = "0.1.30";
|
|
7
7
|
|
|
8
8
|
const timezones = {
|
|
9
9
|
'Asia/Barnaul': 'RU',
|
|
@@ -451,6 +451,17 @@ function getBrowserContext() {
|
|
|
451
451
|
const $screenWidth = screen.width;
|
|
452
452
|
const $title = document.title;
|
|
453
453
|
const $userAgent = window.navigator.userAgent;
|
|
454
|
+
const params = new URLSearchParams(window.location.search);
|
|
455
|
+
const $utmSource = params.get('utm_source');
|
|
456
|
+
const $utmMedium = params.get('utm_medium');
|
|
457
|
+
const $utmCampaign = params.get('utm_campaign');
|
|
458
|
+
const $utmTerm = params.get('utm_term');
|
|
459
|
+
const $utmContent = params.get('utm_content');
|
|
460
|
+
const $utmId = params.get('utm_id');
|
|
461
|
+
const $utmSourcePlatform = params.get('utm_source_platform');
|
|
462
|
+
const $utmCampaignId = params.get('utm_campaign_id');
|
|
463
|
+
const $utmCreativeFormat = params.get('utm_creative_format');
|
|
464
|
+
const $utmMarketingTactic = params.get('utm_marketing_tactic');
|
|
454
465
|
return {
|
|
455
466
|
$locale,
|
|
456
467
|
$location,
|
|
@@ -461,55 +472,43 @@ function getBrowserContext() {
|
|
|
461
472
|
$screenHeight,
|
|
462
473
|
$screenWidth,
|
|
463
474
|
$title,
|
|
464
|
-
$userAgent
|
|
475
|
+
$userAgent,
|
|
476
|
+
$utmSource,
|
|
477
|
+
$utmMedium,
|
|
478
|
+
$utmCampaign,
|
|
479
|
+
$utmTerm,
|
|
480
|
+
$utmContent,
|
|
481
|
+
$utmId,
|
|
482
|
+
$utmSourcePlatform,
|
|
483
|
+
$utmCampaignId,
|
|
484
|
+
$utmCreativeFormat,
|
|
485
|
+
$utmMarketingTactic
|
|
465
486
|
};
|
|
466
487
|
}
|
|
467
488
|
|
|
468
|
-
function getUTMContext() {
|
|
469
|
-
const isBrowser = typeof window !== 'undefined';
|
|
470
|
-
if (!isBrowser) throw new Error('getUTMContext can only be called in browser');
|
|
471
|
-
const params = new URLSearchParams(window.location.search);
|
|
472
|
-
const $utmSource = params.get('utm_source');
|
|
473
|
-
const $utmMedium = params.get('utm_medium');
|
|
474
|
-
const $utmCampaign = params.get('utm_campaign');
|
|
475
|
-
const $utmTerm = params.get('utm_term');
|
|
476
|
-
const $utmContent = params.get('utm_content');
|
|
477
|
-
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, $utmSource ? {
|
|
478
|
-
$utmSource
|
|
479
|
-
} : {}), $utmMedium ? {
|
|
480
|
-
$utmMedium
|
|
481
|
-
} : {}), $utmCampaign ? {
|
|
482
|
-
$utmCampaign
|
|
483
|
-
} : {}), $utmTerm ? {
|
|
484
|
-
$utmTerm
|
|
485
|
-
} : {}), $utmContent ? {
|
|
486
|
-
$utmContent
|
|
487
|
-
} : {});
|
|
488
|
-
}
|
|
489
|
-
|
|
490
489
|
const isBrowser = typeof window !== 'undefined';
|
|
491
490
|
const isServer = !isBrowser;
|
|
492
491
|
const PREF = 'saasco-sdk';
|
|
493
492
|
const SESSION_DURATION = 1000 * 60 * 30;
|
|
494
493
|
const USER_DURATION = 1000 * 60 * 60 * 24 * 365;
|
|
495
494
|
const data = {};
|
|
496
|
-
function getRootDomain() {
|
|
495
|
+
function getRootDomain(url) {
|
|
497
496
|
if (isServer) return;
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
return
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
497
|
+
if (!url) return;
|
|
498
|
+
try {
|
|
499
|
+
const hostname = new URL(url).hostname;
|
|
500
|
+
if (!isValid(hostname)) return;
|
|
501
|
+
const parsed = parse(hostname);
|
|
502
|
+
if ('domain' in parsed && parsed.domain) return parsed.domain;
|
|
503
|
+
} catch (error) {
|
|
504
|
+
// invalid url
|
|
506
505
|
}
|
|
507
|
-
return
|
|
506
|
+
return;
|
|
508
507
|
}
|
|
509
508
|
function setCookie(name, value, ttl) {
|
|
510
509
|
if (isServer) return;
|
|
511
510
|
const expires = new Date(Date.now() + ttl).toUTCString();
|
|
512
|
-
const domain = getRootDomain();
|
|
511
|
+
const domain = getRootDomain(window.location.href);
|
|
513
512
|
const cookieString = `${name}=${encodeURIComponent(value)}; expires=${expires}; path=/${domain ? `; domain=.${domain}` : ''}`;
|
|
514
513
|
document.cookie = cookieString;
|
|
515
514
|
}
|
|
@@ -528,13 +527,13 @@ function getCookie(name) {
|
|
|
528
527
|
}
|
|
529
528
|
function deleteCookie(name) {
|
|
530
529
|
if (isServer) return;
|
|
531
|
-
const domain = getRootDomain();
|
|
530
|
+
const domain = getRootDomain(window.location.href);
|
|
532
531
|
const cookieString = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/${domain ? `; domain=.${domain}` : ''}`;
|
|
533
532
|
document.cookie = cookieString;
|
|
534
533
|
}
|
|
535
534
|
function migrateFromLocalStorage() {
|
|
536
535
|
if (isServer) return;
|
|
537
|
-
const keysToMigrate = [`${PREF}-session-id`, `${PREF}-anonymous-id`, `${PREF}-user-id`, `${PREF}-session-utm-context`];
|
|
536
|
+
const keysToMigrate = [`${PREF}-session-id`, `${PREF}-anonymous-id`, `${PREF}-user-id`, `${PREF}-session-utm-context`, `${PREF}-super-context`];
|
|
538
537
|
keysToMigrate.forEach(key => {
|
|
539
538
|
try {
|
|
540
539
|
const value = localStorage.getItem(key);
|
|
@@ -579,7 +578,11 @@ function storeData(key, value, ttl) {
|
|
|
579
578
|
deleteCookie(fullKey);
|
|
580
579
|
return;
|
|
581
580
|
}
|
|
582
|
-
|
|
581
|
+
const item = {
|
|
582
|
+
value,
|
|
583
|
+
expiry: new Date().getTime() + ttl
|
|
584
|
+
};
|
|
585
|
+
setCookie(fullKey, JSON.stringify(item), ttl);
|
|
583
586
|
}
|
|
584
587
|
function retrieveData(key) {
|
|
585
588
|
if (isServer) {
|
|
@@ -597,7 +600,12 @@ function retrieveData(key) {
|
|
|
597
600
|
return null;
|
|
598
601
|
}
|
|
599
602
|
try {
|
|
600
|
-
|
|
603
|
+
const item = JSON.parse(itemStr);
|
|
604
|
+
if (Date.now() > item.expiry) {
|
|
605
|
+
deleteCookie(fullKey);
|
|
606
|
+
return null;
|
|
607
|
+
}
|
|
608
|
+
return item.value;
|
|
601
609
|
} catch (error) {
|
|
602
610
|
// If JSON parsing fails, remove the corrupted cookie
|
|
603
611
|
deleteCookie(fullKey);
|
|
@@ -633,22 +641,31 @@ function getUserId() {
|
|
|
633
641
|
function setUserId(userId) {
|
|
634
642
|
storeData(`user-id`, userId, USER_DURATION);
|
|
635
643
|
}
|
|
636
|
-
function
|
|
637
|
-
return retrieveData(
|
|
644
|
+
function getSuperContext() {
|
|
645
|
+
return retrieveData('super-context') || {};
|
|
638
646
|
}
|
|
639
|
-
function
|
|
640
|
-
storeData(
|
|
647
|
+
function setSuperContext(superContext) {
|
|
648
|
+
storeData('super-context', superContext, SESSION_DURATION);
|
|
641
649
|
}
|
|
642
|
-
function
|
|
643
|
-
|
|
644
|
-
const
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
650
|
+
function updateSuperContext(browserContext) {
|
|
651
|
+
const existingSuperContext = getSuperContext();
|
|
652
|
+
const defaultSuperContextKeys = ['$utmSource', '$utmMedium', '$utmCampaign', '$utmTerm', '$utmContent', '$utmId', '$utmSourcePlatform', '$utmCampaignId', '$utmCreativeFormat', '$utmMarketingTactic'];
|
|
653
|
+
const superContext = defaultSuperContextKeys.reduce((acc, key) => {
|
|
654
|
+
const value = Object.assign({}, browserContext)[key];
|
|
655
|
+
if (value) acc[key] = value;
|
|
656
|
+
return acc;
|
|
657
|
+
}, existingSuperContext);
|
|
658
|
+
// Only set referrer if it's from a different root domain
|
|
659
|
+
// Prevents setting referrer when going between subdomains of the same root domain
|
|
660
|
+
if (browserContext.$referrer) {
|
|
661
|
+
const referrerRootDomain = getRootDomain(browserContext.$referrer);
|
|
662
|
+
const currentRootDomain = getRootDomain(browserContext.$href);
|
|
663
|
+
if (referrerRootDomain && currentRootDomain && referrerRootDomain !== currentRootDomain) {
|
|
664
|
+
superContext['$referrer'] = browserContext.$referrer;
|
|
665
|
+
}
|
|
649
666
|
}
|
|
650
|
-
|
|
651
|
-
return
|
|
667
|
+
setSuperContext(superContext);
|
|
668
|
+
return superContext;
|
|
652
669
|
}
|
|
653
670
|
class Saasco {
|
|
654
671
|
/**
|
|
@@ -729,15 +746,16 @@ class Saasco {
|
|
|
729
746
|
const sessionId = (hasAction ? undefined : actionOrPayload.sessionId) || getSessionId();
|
|
730
747
|
const anonymousId = (hasAction ? undefined : actionOrPayload.anonymousId) || getAnonymousId();
|
|
731
748
|
const distinctId = (hasAction ? undefined : actionOrPayload.userId) || getUserId();
|
|
732
|
-
// Only gets browser and
|
|
749
|
+
// Only gets browser and super context if in the browser
|
|
733
750
|
let browserContext;
|
|
734
|
-
let
|
|
751
|
+
let superContext;
|
|
735
752
|
if (isBrowser) {
|
|
736
753
|
browserContext = getBrowserContext();
|
|
737
|
-
|
|
738
|
-
const sessionUTMContext = handleSessionUTMContext();
|
|
739
|
-
if (sessionUTMContext) utmContext = sessionUTMContext;
|
|
754
|
+
superContext = updateSuperContext(browserContext);
|
|
740
755
|
}
|
|
756
|
+
const payloadJSON = Object.assign(Object.assign(Object.assign({}, browserContext), superContext), {
|
|
757
|
+
properties: properties || {}
|
|
758
|
+
});
|
|
741
759
|
const data = {
|
|
742
760
|
id: v4(),
|
|
743
761
|
timestamp: new Date().toISOString(),
|
|
@@ -747,9 +765,7 @@ class Saasco {
|
|
|
747
765
|
anonymousId,
|
|
748
766
|
distinctId,
|
|
749
767
|
projectId: this.config.projectId,
|
|
750
|
-
payload: JSON.stringify(
|
|
751
|
-
properties: properties || {}
|
|
752
|
-
})),
|
|
768
|
+
payload: JSON.stringify(payloadJSON),
|
|
753
769
|
source: isBrowser ? 'client' : 'server',
|
|
754
770
|
context: JSON.stringify(context || {})
|
|
755
771
|
};
|
|
@@ -830,8 +846,8 @@ class Saasco {
|
|
|
830
846
|
*
|
|
831
847
|
*/
|
|
832
848
|
logout() {
|
|
833
|
-
// Clear
|
|
834
|
-
|
|
849
|
+
// Clear super context data on logout
|
|
850
|
+
setSuperContext(null);
|
|
835
851
|
this.identify(null);
|
|
836
852
|
}
|
|
837
853
|
/**
|
|
@@ -955,14 +971,17 @@ const browserContextSchema = z.object({
|
|
|
955
971
|
$screenHeight: z.number(),
|
|
956
972
|
$screenWidth: z.number(),
|
|
957
973
|
$title: z.string(),
|
|
958
|
-
$userAgent: z.string()
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
$
|
|
962
|
-
$
|
|
963
|
-
$
|
|
964
|
-
$
|
|
965
|
-
$
|
|
974
|
+
$userAgent: z.string(),
|
|
975
|
+
$utmSource: z.string().nullable(),
|
|
976
|
+
$utmMedium: z.string().nullable(),
|
|
977
|
+
$utmCampaign: z.string().nullable(),
|
|
978
|
+
$utmTerm: z.string().nullable(),
|
|
979
|
+
$utmContent: z.string().nullable(),
|
|
980
|
+
$utmId: z.string().nullable(),
|
|
981
|
+
$utmSourcePlatform: z.string().nullable(),
|
|
982
|
+
$utmCampaignId: z.string().nullable(),
|
|
983
|
+
$utmCreativeFormat: z.string().nullable(),
|
|
984
|
+
$utmMarketingTactic: z.string().nullable()
|
|
966
985
|
});
|
|
967
986
|
|
|
968
|
-
export { Saasco, browserContextSchema, getBrowserContext,
|
|
987
|
+
export { Saasco, browserContextSchema, getBrowserContext, timezones };
|
package/package.json
CHANGED
package/src/index.d.ts
CHANGED
|
@@ -10,6 +10,16 @@ export declare const browserContextSchema: z.ZodObject<{
|
|
|
10
10
|
$screenWidth: z.ZodNumber;
|
|
11
11
|
$title: z.ZodString;
|
|
12
12
|
$userAgent: z.ZodString;
|
|
13
|
+
$utmSource: z.ZodNullable<z.ZodString>;
|
|
14
|
+
$utmMedium: z.ZodNullable<z.ZodString>;
|
|
15
|
+
$utmCampaign: z.ZodNullable<z.ZodString>;
|
|
16
|
+
$utmTerm: z.ZodNullable<z.ZodString>;
|
|
17
|
+
$utmContent: z.ZodNullable<z.ZodString>;
|
|
18
|
+
$utmId: z.ZodNullable<z.ZodString>;
|
|
19
|
+
$utmSourcePlatform: z.ZodNullable<z.ZodString>;
|
|
20
|
+
$utmCampaignId: z.ZodNullable<z.ZodString>;
|
|
21
|
+
$utmCreativeFormat: z.ZodNullable<z.ZodString>;
|
|
22
|
+
$utmMarketingTactic: z.ZodNullable<z.ZodString>;
|
|
13
23
|
}, "strip", z.ZodTypeAny, {
|
|
14
24
|
$locale: string;
|
|
15
25
|
$location: string;
|
|
@@ -21,6 +31,16 @@ export declare const browserContextSchema: z.ZodObject<{
|
|
|
21
31
|
$screenWidth: number;
|
|
22
32
|
$title: string;
|
|
23
33
|
$userAgent: string;
|
|
34
|
+
$utmSource: string | null;
|
|
35
|
+
$utmMedium: string | null;
|
|
36
|
+
$utmCampaign: string | null;
|
|
37
|
+
$utmTerm: string | null;
|
|
38
|
+
$utmContent: string | null;
|
|
39
|
+
$utmId: string | null;
|
|
40
|
+
$utmSourcePlatform: string | null;
|
|
41
|
+
$utmCampaignId: string | null;
|
|
42
|
+
$utmCreativeFormat: string | null;
|
|
43
|
+
$utmMarketingTactic: string | null;
|
|
24
44
|
}, {
|
|
25
45
|
$locale: string;
|
|
26
46
|
$location: string;
|
|
@@ -32,25 +52,16 @@ export declare const browserContextSchema: z.ZodObject<{
|
|
|
32
52
|
$screenWidth: number;
|
|
33
53
|
$title: string;
|
|
34
54
|
$userAgent: string;
|
|
55
|
+
$utmSource: string | null;
|
|
56
|
+
$utmMedium: string | null;
|
|
57
|
+
$utmCampaign: string | null;
|
|
58
|
+
$utmTerm: string | null;
|
|
59
|
+
$utmContent: string | null;
|
|
60
|
+
$utmId: string | null;
|
|
61
|
+
$utmSourcePlatform: string | null;
|
|
62
|
+
$utmCampaignId: string | null;
|
|
63
|
+
$utmCreativeFormat: string | null;
|
|
64
|
+
$utmMarketingTactic: string | null;
|
|
35
65
|
}>;
|
|
36
66
|
export type BrowserContext = z.infer<typeof browserContextSchema>;
|
|
37
|
-
export
|
|
38
|
-
$utmSource: z.ZodOptional<z.ZodString>;
|
|
39
|
-
$utmMedium: z.ZodOptional<z.ZodString>;
|
|
40
|
-
$utmCampaign: z.ZodOptional<z.ZodString>;
|
|
41
|
-
$utmTerm: z.ZodOptional<z.ZodString>;
|
|
42
|
-
$utmContent: z.ZodOptional<z.ZodString>;
|
|
43
|
-
}, "strip", z.ZodTypeAny, {
|
|
44
|
-
$utmSource?: string | undefined;
|
|
45
|
-
$utmMedium?: string | undefined;
|
|
46
|
-
$utmCampaign?: string | undefined;
|
|
47
|
-
$utmTerm?: string | undefined;
|
|
48
|
-
$utmContent?: string | undefined;
|
|
49
|
-
}, {
|
|
50
|
-
$utmSource?: string | undefined;
|
|
51
|
-
$utmMedium?: string | undefined;
|
|
52
|
-
$utmCampaign?: string | undefined;
|
|
53
|
-
$utmTerm?: string | undefined;
|
|
54
|
-
$utmContent?: string | undefined;
|
|
55
|
-
}>;
|
|
56
|
-
export type UTMContext = z.infer<typeof utmContextSchema>;
|
|
67
|
+
export type SuperContext = Record<string, any>;
|