@blotoutio/providers-bing-sdk 1.53.1 → 1.55.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.
- package/index.cjs.js +156 -1
- package/index.js +156 -1
- package/index.mjs +156 -1
- package/package.json +1 -1
package/index.cjs.js
CHANGED
|
@@ -37,6 +37,40 @@ const hasUserConsentForProvider = (consent, provider) => {
|
|
|
37
37
|
return allowed;
|
|
38
38
|
};
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Known ad-network click ID query parameters and the human-readable provider
|
|
42
|
+
* label each one maps to. Used by the CDN worker to resolve `inSessionTouch`
|
|
43
|
+
* and by the analytics API to classify paid-media touch sessions.
|
|
44
|
+
*
|
|
45
|
+
* Keep this list in sync with `defaultParams` in queryParams.ts when new
|
|
46
|
+
* click ID providers are added.
|
|
47
|
+
*/
|
|
48
|
+
const CLICK_IDS = [
|
|
49
|
+
{ param: 'fbclid', label: 'Facebook' }, // Facebook Ads
|
|
50
|
+
{ param: 'gclid', label: 'Google' }, // Google Ads (click)
|
|
51
|
+
{ param: 'gbraid', label: 'Google' }, // Google Ads (iOS app)
|
|
52
|
+
{ param: 'wbraid', label: 'Google' }, // Google Ads (iOS web)
|
|
53
|
+
{ param: 'msclkid', label: 'Bing' }, // Microsoft Bing Ads
|
|
54
|
+
{ param: 'ttclid', label: 'TikTok' }, // TikTok Ads
|
|
55
|
+
{ param: 'ScCid', label: 'Snapchat' }, // Snapchat Ads
|
|
56
|
+
{ param: 'epik', label: 'Pinterest' }, // Pinterest Ads
|
|
57
|
+
{ param: 'li_fat_id', label: 'LinkedIn' }, // LinkedIn Ads
|
|
58
|
+
{ param: 'twclid', label: 'Twitter' }, // X (Twitter) Ads
|
|
59
|
+
{ param: 'rdt_cid', label: 'Reddit' }, // Reddit Ads
|
|
60
|
+
{ param: 'aleid', label: 'AppLovin' }, // AppLovin
|
|
61
|
+
{ param: 'tabclid', label: 'Taboola' }, // Taboola
|
|
62
|
+
{ param: 'obclid', label: 'Outbrain' }, // Outbrain
|
|
63
|
+
{ param: 'trybe', label: 'Trybe' }, // Trybe
|
|
64
|
+
{ param: '_kx', label: 'Klaviyo' }, // Klaviyo email campaigns
|
|
65
|
+
{ param: 'mc_eid', label: 'Mailchimp' }, // Mailchimp email campaigns
|
|
66
|
+
{ param: 'ttd_id', label: 'The Trade Desk' }, // The Trade Desk programmatic
|
|
67
|
+
{ param: 'evsclid', label: 'EvoSearch' }, // EvoSearch
|
|
68
|
+
{ param: 'li_did', label: 'Live Intent' }, // LiveIntent device-level ad
|
|
69
|
+
{ param: '_raclid', label: 'Rumble' }, // Rumble Ads
|
|
70
|
+
{ param: 'ref_id', label: 'StackAdapt' }, // StackAdapt programmatic
|
|
71
|
+
{ param: 'duel_a', label: 'Duel' }, // Duel referral/advocacy
|
|
72
|
+
];
|
|
73
|
+
|
|
40
74
|
const expand = (str) => str.split(',').flatMap((entry) => {
|
|
41
75
|
if (!entry.includes('-')) {
|
|
42
76
|
return entry;
|
|
@@ -393,6 +427,127 @@ const usStates = new Map([
|
|
|
393
427
|
]);
|
|
394
428
|
new Set([...isoCountries.keys(), ...usStates.keys()]);
|
|
395
429
|
|
|
430
|
+
/**
|
|
431
|
+
* Exact utm_source normalization (lowercase key → canonical name).
|
|
432
|
+
*
|
|
433
|
+
* Use exact match when the key is short, generic, or must not accidentally
|
|
434
|
+
* absorb variant spellings (e.g. "impact" must not match "impact_radius").
|
|
435
|
+
*
|
|
436
|
+
* Ordering: Paid (search/social → ad networks → affiliates) →
|
|
437
|
+
* Organic (AI/discovery) → Retention (email → SMS → push → post-purchase)
|
|
438
|
+
*/
|
|
439
|
+
const UTM_SOURCE_EXACT = {
|
|
440
|
+
// ── Paid – Search & Social ────────────────────────────────────────────────
|
|
441
|
+
google: 'Google',
|
|
442
|
+
adwords: 'Google',
|
|
443
|
+
youtube: 'Google',
|
|
444
|
+
yt: 'Google',
|
|
445
|
+
meta: 'Facebook',
|
|
446
|
+
facebook: 'Facebook',
|
|
447
|
+
instagram: 'Facebook',
|
|
448
|
+
ig: 'Facebook',
|
|
449
|
+
igshopping: 'Facebook',
|
|
450
|
+
threads: 'Facebook',
|
|
451
|
+
twitter: 'Twitter',
|
|
452
|
+
snapchat: 'Snapchat',
|
|
453
|
+
pinterest: 'Pinterest',
|
|
454
|
+
bing: 'Bing',
|
|
455
|
+
microsoft: 'Bing',
|
|
456
|
+
tiktok: 'TikTok',
|
|
457
|
+
// ── Paid – Ad Networks ───────────────────────────────────────────────────
|
|
458
|
+
rtbhouse: 'RTB House',
|
|
459
|
+
applovin: 'AppLovin',
|
|
460
|
+
ttd: 'The Trade Desk',
|
|
461
|
+
amazondsp: 'Amazon DSP',
|
|
462
|
+
axon: 'Axon',
|
|
463
|
+
duel: 'Duel',
|
|
464
|
+
// ── Paid – Affiliates ────────────────────────────────────────────────────
|
|
465
|
+
awin: 'Awin',
|
|
466
|
+
'affiliate-cj': 'CJ Affiliate',
|
|
467
|
+
impact: 'Impact',
|
|
468
|
+
rakuten: 'Rakuten',
|
|
469
|
+
superfiliate: 'Superfiliate',
|
|
470
|
+
// ── Organic – AI & Discovery ─────────────────────────────────────────────
|
|
471
|
+
perplexity: 'Perplexity',
|
|
472
|
+
chatgpt: 'ChatGPT',
|
|
473
|
+
'chatgpt.com': 'ChatGPT',
|
|
474
|
+
openai: 'ChatGPT',
|
|
475
|
+
'copilot.com': 'Microsoft Copilot',
|
|
476
|
+
copilot: 'Microsoft Copilot',
|
|
477
|
+
applenews: 'Apple News',
|
|
478
|
+
whatsapp: 'WhatsApp',
|
|
479
|
+
podcast: 'Podcast',
|
|
480
|
+
// ── Retention – Email ────────────────────────────────────────────────────
|
|
481
|
+
mailchimp: 'Mailchimp',
|
|
482
|
+
omnisend: 'Omnisend',
|
|
483
|
+
iterable: 'Iterable',
|
|
484
|
+
listrak: 'Listrak',
|
|
485
|
+
sailthru: 'Sailthru',
|
|
486
|
+
// ── Retention – Push ─────────────────────────────────────────────────────
|
|
487
|
+
pushowl: 'PushOwl',
|
|
488
|
+
// ── Retention – Post-purchase / Payment ──────────────────────────────────
|
|
489
|
+
narvar: 'Narvar',
|
|
490
|
+
shop_app: 'Shop App',
|
|
491
|
+
salesforce: 'Salesforce',
|
|
492
|
+
yotpo: 'Yotpo',
|
|
493
|
+
};
|
|
494
|
+
/**
|
|
495
|
+
* Partial utm_source normalization (startsWith prefix check, lowercase).
|
|
496
|
+
*
|
|
497
|
+
* Checked after exact match so short exact keys (e.g. "ig", "yt") win first.
|
|
498
|
+
*/
|
|
499
|
+
const UTM_SOURCE_PARTIAL = [
|
|
500
|
+
// ── Paid – Social ─────────────────────────────────────────────────────────
|
|
501
|
+
{ prefix: 'tiktok', name: 'TikTok' },
|
|
502
|
+
// ── Paid – Ad Networks ───────────────────────────────────────────────────
|
|
503
|
+
{ prefix: 'criteo', name: 'Criteo' },
|
|
504
|
+
// ── Retention – Email ────────────────────────────────────────────────────
|
|
505
|
+
{ prefix: 'klaviyo', name: 'Klaviyo' },
|
|
506
|
+
// ── Retention – SMS ──────────────────────────────────────────────────────
|
|
507
|
+
{ prefix: 'attentive', name: 'Attentive' },
|
|
508
|
+
{ prefix: 'postscript', name: 'Postscript' },
|
|
509
|
+
// ── Retention – Post-purchase / Payment ──────────────────────────────────
|
|
510
|
+
{ prefix: 'afterpay', name: 'Afterpay' },
|
|
511
|
+
{ prefix: 'klarna', name: 'Klarna' },
|
|
512
|
+
];
|
|
513
|
+
const ORGANIC_SEARCH_ENGINES = [
|
|
514
|
+
{ match: 'google', name: 'Google' },
|
|
515
|
+
{ match: 'bing', name: 'Bing' },
|
|
516
|
+
{ match: 'yahoo', name: 'Yahoo' },
|
|
517
|
+
{ match: 'duckduckgo', name: 'DuckDuckGo' },
|
|
518
|
+
{ match: 'baidu', name: 'Baidu' },
|
|
519
|
+
{ match: 'yandex', name: 'Yandex' },
|
|
520
|
+
{ match: 'brave', name: 'Brave' },
|
|
521
|
+
];
|
|
522
|
+
const KNOWN_REFERRAL_PLATFORMS = [
|
|
523
|
+
{ match: 'facebook', name: 'Facebook' },
|
|
524
|
+
{ match: 'instagram', name: 'Facebook' },
|
|
525
|
+
{ match: 'twitter', name: 'Twitter' },
|
|
526
|
+
{ match: 'x.com', name: 'Twitter' },
|
|
527
|
+
{ match: 'tiktok', name: 'TikTok' },
|
|
528
|
+
{ match: 'pinterest', name: 'Pinterest' },
|
|
529
|
+
{ match: 'linkedin', name: 'LinkedIn' },
|
|
530
|
+
{ match: 'youtube', name: 'YouTube' },
|
|
531
|
+
{ match: 'chatgpt', name: 'ChatGPT' },
|
|
532
|
+
{ match: 'claude', name: 'Claude' },
|
|
533
|
+
{ match: 'perplexity', name: 'Perplexity' },
|
|
534
|
+
{ match: 'shop.app', name: 'Shop App' },
|
|
535
|
+
{ match: 'amazon', name: 'Amazon' },
|
|
536
|
+
{ match: 'attentive', name: 'Attentive' },
|
|
537
|
+
];
|
|
538
|
+
const OFFLINE_TOUCH = 'Blotout_Offline';
|
|
539
|
+
new Set([
|
|
540
|
+
...CLICK_IDS.map((c) => c.label),
|
|
541
|
+
...Object.values(UTM_SOURCE_EXACT),
|
|
542
|
+
...UTM_SOURCE_PARTIAL.map((e) => e.name),
|
|
543
|
+
...ORGANIC_SEARCH_ENGINES.map((e) => `Organic Search - ${e.name}`),
|
|
544
|
+
...KNOWN_REFERRAL_PLATFORMS.map((e) => `Referral - ${e.name}`),
|
|
545
|
+
'Referral - Other',
|
|
546
|
+
'Direct Traffic',
|
|
547
|
+
'Other',
|
|
548
|
+
OFFLINE_TOUCH,
|
|
549
|
+
]);
|
|
550
|
+
|
|
396
551
|
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
397
552
|
const isConsentEnabled = (consent) => hasUserConsentForProvider(consent, packageName);
|
|
398
553
|
const consent = ({ consentData }) => {
|
|
@@ -539,7 +694,7 @@ const handleTag = ({ data, eventName, manifestVariables, }) => {
|
|
|
539
694
|
|
|
540
695
|
const tag = ({ data, eventName, manifestVariables }) => {
|
|
541
696
|
const payload = {
|
|
542
|
-
sdkVersion: "1.
|
|
697
|
+
sdkVersion: "1.55.0" ,
|
|
543
698
|
};
|
|
544
699
|
if (window.edgeUET && manifestVariables['enableBrowser'] === '1') {
|
|
545
700
|
handleTag({ data, eventName, manifestVariables });
|
package/index.js
CHANGED
|
@@ -38,6 +38,40 @@ var ProvidersBingSdk = (function () {
|
|
|
38
38
|
return allowed;
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
+
/**
|
|
42
|
+
* Known ad-network click ID query parameters and the human-readable provider
|
|
43
|
+
* label each one maps to. Used by the CDN worker to resolve `inSessionTouch`
|
|
44
|
+
* and by the analytics API to classify paid-media touch sessions.
|
|
45
|
+
*
|
|
46
|
+
* Keep this list in sync with `defaultParams` in queryParams.ts when new
|
|
47
|
+
* click ID providers are added.
|
|
48
|
+
*/
|
|
49
|
+
const CLICK_IDS = [
|
|
50
|
+
{ param: 'fbclid', label: 'Facebook' }, // Facebook Ads
|
|
51
|
+
{ param: 'gclid', label: 'Google' }, // Google Ads (click)
|
|
52
|
+
{ param: 'gbraid', label: 'Google' }, // Google Ads (iOS app)
|
|
53
|
+
{ param: 'wbraid', label: 'Google' }, // Google Ads (iOS web)
|
|
54
|
+
{ param: 'msclkid', label: 'Bing' }, // Microsoft Bing Ads
|
|
55
|
+
{ param: 'ttclid', label: 'TikTok' }, // TikTok Ads
|
|
56
|
+
{ param: 'ScCid', label: 'Snapchat' }, // Snapchat Ads
|
|
57
|
+
{ param: 'epik', label: 'Pinterest' }, // Pinterest Ads
|
|
58
|
+
{ param: 'li_fat_id', label: 'LinkedIn' }, // LinkedIn Ads
|
|
59
|
+
{ param: 'twclid', label: 'Twitter' }, // X (Twitter) Ads
|
|
60
|
+
{ param: 'rdt_cid', label: 'Reddit' }, // Reddit Ads
|
|
61
|
+
{ param: 'aleid', label: 'AppLovin' }, // AppLovin
|
|
62
|
+
{ param: 'tabclid', label: 'Taboola' }, // Taboola
|
|
63
|
+
{ param: 'obclid', label: 'Outbrain' }, // Outbrain
|
|
64
|
+
{ param: 'trybe', label: 'Trybe' }, // Trybe
|
|
65
|
+
{ param: '_kx', label: 'Klaviyo' }, // Klaviyo email campaigns
|
|
66
|
+
{ param: 'mc_eid', label: 'Mailchimp' }, // Mailchimp email campaigns
|
|
67
|
+
{ param: 'ttd_id', label: 'The Trade Desk' }, // The Trade Desk programmatic
|
|
68
|
+
{ param: 'evsclid', label: 'EvoSearch' }, // EvoSearch
|
|
69
|
+
{ param: 'li_did', label: 'Live Intent' }, // LiveIntent device-level ad
|
|
70
|
+
{ param: '_raclid', label: 'Rumble' }, // Rumble Ads
|
|
71
|
+
{ param: 'ref_id', label: 'StackAdapt' }, // StackAdapt programmatic
|
|
72
|
+
{ param: 'duel_a', label: 'Duel' }, // Duel referral/advocacy
|
|
73
|
+
];
|
|
74
|
+
|
|
41
75
|
const expand = (str) => str.split(',').flatMap((entry) => {
|
|
42
76
|
if (!entry.includes('-')) {
|
|
43
77
|
return entry;
|
|
@@ -394,6 +428,127 @@ var ProvidersBingSdk = (function () {
|
|
|
394
428
|
]);
|
|
395
429
|
new Set([...isoCountries.keys(), ...usStates.keys()]);
|
|
396
430
|
|
|
431
|
+
/**
|
|
432
|
+
* Exact utm_source normalization (lowercase key → canonical name).
|
|
433
|
+
*
|
|
434
|
+
* Use exact match when the key is short, generic, or must not accidentally
|
|
435
|
+
* absorb variant spellings (e.g. "impact" must not match "impact_radius").
|
|
436
|
+
*
|
|
437
|
+
* Ordering: Paid (search/social → ad networks → affiliates) →
|
|
438
|
+
* Organic (AI/discovery) → Retention (email → SMS → push → post-purchase)
|
|
439
|
+
*/
|
|
440
|
+
const UTM_SOURCE_EXACT = {
|
|
441
|
+
// ── Paid – Search & Social ────────────────────────────────────────────────
|
|
442
|
+
google: 'Google',
|
|
443
|
+
adwords: 'Google',
|
|
444
|
+
youtube: 'Google',
|
|
445
|
+
yt: 'Google',
|
|
446
|
+
meta: 'Facebook',
|
|
447
|
+
facebook: 'Facebook',
|
|
448
|
+
instagram: 'Facebook',
|
|
449
|
+
ig: 'Facebook',
|
|
450
|
+
igshopping: 'Facebook',
|
|
451
|
+
threads: 'Facebook',
|
|
452
|
+
twitter: 'Twitter',
|
|
453
|
+
snapchat: 'Snapchat',
|
|
454
|
+
pinterest: 'Pinterest',
|
|
455
|
+
bing: 'Bing',
|
|
456
|
+
microsoft: 'Bing',
|
|
457
|
+
tiktok: 'TikTok',
|
|
458
|
+
// ── Paid – Ad Networks ───────────────────────────────────────────────────
|
|
459
|
+
rtbhouse: 'RTB House',
|
|
460
|
+
applovin: 'AppLovin',
|
|
461
|
+
ttd: 'The Trade Desk',
|
|
462
|
+
amazondsp: 'Amazon DSP',
|
|
463
|
+
axon: 'Axon',
|
|
464
|
+
duel: 'Duel',
|
|
465
|
+
// ── Paid – Affiliates ────────────────────────────────────────────────────
|
|
466
|
+
awin: 'Awin',
|
|
467
|
+
'affiliate-cj': 'CJ Affiliate',
|
|
468
|
+
impact: 'Impact',
|
|
469
|
+
rakuten: 'Rakuten',
|
|
470
|
+
superfiliate: 'Superfiliate',
|
|
471
|
+
// ── Organic – AI & Discovery ─────────────────────────────────────────────
|
|
472
|
+
perplexity: 'Perplexity',
|
|
473
|
+
chatgpt: 'ChatGPT',
|
|
474
|
+
'chatgpt.com': 'ChatGPT',
|
|
475
|
+
openai: 'ChatGPT',
|
|
476
|
+
'copilot.com': 'Microsoft Copilot',
|
|
477
|
+
copilot: 'Microsoft Copilot',
|
|
478
|
+
applenews: 'Apple News',
|
|
479
|
+
whatsapp: 'WhatsApp',
|
|
480
|
+
podcast: 'Podcast',
|
|
481
|
+
// ── Retention – Email ────────────────────────────────────────────────────
|
|
482
|
+
mailchimp: 'Mailchimp',
|
|
483
|
+
omnisend: 'Omnisend',
|
|
484
|
+
iterable: 'Iterable',
|
|
485
|
+
listrak: 'Listrak',
|
|
486
|
+
sailthru: 'Sailthru',
|
|
487
|
+
// ── Retention – Push ─────────────────────────────────────────────────────
|
|
488
|
+
pushowl: 'PushOwl',
|
|
489
|
+
// ── Retention – Post-purchase / Payment ──────────────────────────────────
|
|
490
|
+
narvar: 'Narvar',
|
|
491
|
+
shop_app: 'Shop App',
|
|
492
|
+
salesforce: 'Salesforce',
|
|
493
|
+
yotpo: 'Yotpo',
|
|
494
|
+
};
|
|
495
|
+
/**
|
|
496
|
+
* Partial utm_source normalization (startsWith prefix check, lowercase).
|
|
497
|
+
*
|
|
498
|
+
* Checked after exact match so short exact keys (e.g. "ig", "yt") win first.
|
|
499
|
+
*/
|
|
500
|
+
const UTM_SOURCE_PARTIAL = [
|
|
501
|
+
// ── Paid – Social ─────────────────────────────────────────────────────────
|
|
502
|
+
{ prefix: 'tiktok', name: 'TikTok' },
|
|
503
|
+
// ── Paid – Ad Networks ───────────────────────────────────────────────────
|
|
504
|
+
{ prefix: 'criteo', name: 'Criteo' },
|
|
505
|
+
// ── Retention – Email ────────────────────────────────────────────────────
|
|
506
|
+
{ prefix: 'klaviyo', name: 'Klaviyo' },
|
|
507
|
+
// ── Retention – SMS ──────────────────────────────────────────────────────
|
|
508
|
+
{ prefix: 'attentive', name: 'Attentive' },
|
|
509
|
+
{ prefix: 'postscript', name: 'Postscript' },
|
|
510
|
+
// ── Retention – Post-purchase / Payment ──────────────────────────────────
|
|
511
|
+
{ prefix: 'afterpay', name: 'Afterpay' },
|
|
512
|
+
{ prefix: 'klarna', name: 'Klarna' },
|
|
513
|
+
];
|
|
514
|
+
const ORGANIC_SEARCH_ENGINES = [
|
|
515
|
+
{ match: 'google', name: 'Google' },
|
|
516
|
+
{ match: 'bing', name: 'Bing' },
|
|
517
|
+
{ match: 'yahoo', name: 'Yahoo' },
|
|
518
|
+
{ match: 'duckduckgo', name: 'DuckDuckGo' },
|
|
519
|
+
{ match: 'baidu', name: 'Baidu' },
|
|
520
|
+
{ match: 'yandex', name: 'Yandex' },
|
|
521
|
+
{ match: 'brave', name: 'Brave' },
|
|
522
|
+
];
|
|
523
|
+
const KNOWN_REFERRAL_PLATFORMS = [
|
|
524
|
+
{ match: 'facebook', name: 'Facebook' },
|
|
525
|
+
{ match: 'instagram', name: 'Facebook' },
|
|
526
|
+
{ match: 'twitter', name: 'Twitter' },
|
|
527
|
+
{ match: 'x.com', name: 'Twitter' },
|
|
528
|
+
{ match: 'tiktok', name: 'TikTok' },
|
|
529
|
+
{ match: 'pinterest', name: 'Pinterest' },
|
|
530
|
+
{ match: 'linkedin', name: 'LinkedIn' },
|
|
531
|
+
{ match: 'youtube', name: 'YouTube' },
|
|
532
|
+
{ match: 'chatgpt', name: 'ChatGPT' },
|
|
533
|
+
{ match: 'claude', name: 'Claude' },
|
|
534
|
+
{ match: 'perplexity', name: 'Perplexity' },
|
|
535
|
+
{ match: 'shop.app', name: 'Shop App' },
|
|
536
|
+
{ match: 'amazon', name: 'Amazon' },
|
|
537
|
+
{ match: 'attentive', name: 'Attentive' },
|
|
538
|
+
];
|
|
539
|
+
const OFFLINE_TOUCH = 'Blotout_Offline';
|
|
540
|
+
new Set([
|
|
541
|
+
...CLICK_IDS.map((c) => c.label),
|
|
542
|
+
...Object.values(UTM_SOURCE_EXACT),
|
|
543
|
+
...UTM_SOURCE_PARTIAL.map((e) => e.name),
|
|
544
|
+
...ORGANIC_SEARCH_ENGINES.map((e) => `Organic Search - ${e.name}`),
|
|
545
|
+
...KNOWN_REFERRAL_PLATFORMS.map((e) => `Referral - ${e.name}`),
|
|
546
|
+
'Referral - Other',
|
|
547
|
+
'Direct Traffic',
|
|
548
|
+
'Other',
|
|
549
|
+
OFFLINE_TOUCH,
|
|
550
|
+
]);
|
|
551
|
+
|
|
397
552
|
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
398
553
|
const isConsentEnabled = (consent) => hasUserConsentForProvider(consent, packageName);
|
|
399
554
|
const consent = ({ consentData }) => {
|
|
@@ -540,7 +695,7 @@ var ProvidersBingSdk = (function () {
|
|
|
540
695
|
|
|
541
696
|
const tag = ({ data, eventName, manifestVariables }) => {
|
|
542
697
|
const payload = {
|
|
543
|
-
sdkVersion: "1.
|
|
698
|
+
sdkVersion: "1.55.0" ,
|
|
544
699
|
};
|
|
545
700
|
if (window.edgeUET && manifestVariables['enableBrowser'] === '1') {
|
|
546
701
|
handleTag({ data, eventName, manifestVariables });
|
package/index.mjs
CHANGED
|
@@ -35,6 +35,40 @@ const hasUserConsentForProvider = (consent, provider) => {
|
|
|
35
35
|
return allowed;
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Known ad-network click ID query parameters and the human-readable provider
|
|
40
|
+
* label each one maps to. Used by the CDN worker to resolve `inSessionTouch`
|
|
41
|
+
* and by the analytics API to classify paid-media touch sessions.
|
|
42
|
+
*
|
|
43
|
+
* Keep this list in sync with `defaultParams` in queryParams.ts when new
|
|
44
|
+
* click ID providers are added.
|
|
45
|
+
*/
|
|
46
|
+
const CLICK_IDS = [
|
|
47
|
+
{ param: 'fbclid', label: 'Facebook' }, // Facebook Ads
|
|
48
|
+
{ param: 'gclid', label: 'Google' }, // Google Ads (click)
|
|
49
|
+
{ param: 'gbraid', label: 'Google' }, // Google Ads (iOS app)
|
|
50
|
+
{ param: 'wbraid', label: 'Google' }, // Google Ads (iOS web)
|
|
51
|
+
{ param: 'msclkid', label: 'Bing' }, // Microsoft Bing Ads
|
|
52
|
+
{ param: 'ttclid', label: 'TikTok' }, // TikTok Ads
|
|
53
|
+
{ param: 'ScCid', label: 'Snapchat' }, // Snapchat Ads
|
|
54
|
+
{ param: 'epik', label: 'Pinterest' }, // Pinterest Ads
|
|
55
|
+
{ param: 'li_fat_id', label: 'LinkedIn' }, // LinkedIn Ads
|
|
56
|
+
{ param: 'twclid', label: 'Twitter' }, // X (Twitter) Ads
|
|
57
|
+
{ param: 'rdt_cid', label: 'Reddit' }, // Reddit Ads
|
|
58
|
+
{ param: 'aleid', label: 'AppLovin' }, // AppLovin
|
|
59
|
+
{ param: 'tabclid', label: 'Taboola' }, // Taboola
|
|
60
|
+
{ param: 'obclid', label: 'Outbrain' }, // Outbrain
|
|
61
|
+
{ param: 'trybe', label: 'Trybe' }, // Trybe
|
|
62
|
+
{ param: '_kx', label: 'Klaviyo' }, // Klaviyo email campaigns
|
|
63
|
+
{ param: 'mc_eid', label: 'Mailchimp' }, // Mailchimp email campaigns
|
|
64
|
+
{ param: 'ttd_id', label: 'The Trade Desk' }, // The Trade Desk programmatic
|
|
65
|
+
{ param: 'evsclid', label: 'EvoSearch' }, // EvoSearch
|
|
66
|
+
{ param: 'li_did', label: 'Live Intent' }, // LiveIntent device-level ad
|
|
67
|
+
{ param: '_raclid', label: 'Rumble' }, // Rumble Ads
|
|
68
|
+
{ param: 'ref_id', label: 'StackAdapt' }, // StackAdapt programmatic
|
|
69
|
+
{ param: 'duel_a', label: 'Duel' }, // Duel referral/advocacy
|
|
70
|
+
];
|
|
71
|
+
|
|
38
72
|
const expand = (str) => str.split(',').flatMap((entry) => {
|
|
39
73
|
if (!entry.includes('-')) {
|
|
40
74
|
return entry;
|
|
@@ -391,6 +425,127 @@ const usStates = new Map([
|
|
|
391
425
|
]);
|
|
392
426
|
new Set([...isoCountries.keys(), ...usStates.keys()]);
|
|
393
427
|
|
|
428
|
+
/**
|
|
429
|
+
* Exact utm_source normalization (lowercase key → canonical name).
|
|
430
|
+
*
|
|
431
|
+
* Use exact match when the key is short, generic, or must not accidentally
|
|
432
|
+
* absorb variant spellings (e.g. "impact" must not match "impact_radius").
|
|
433
|
+
*
|
|
434
|
+
* Ordering: Paid (search/social → ad networks → affiliates) →
|
|
435
|
+
* Organic (AI/discovery) → Retention (email → SMS → push → post-purchase)
|
|
436
|
+
*/
|
|
437
|
+
const UTM_SOURCE_EXACT = {
|
|
438
|
+
// ── Paid – Search & Social ────────────────────────────────────────────────
|
|
439
|
+
google: 'Google',
|
|
440
|
+
adwords: 'Google',
|
|
441
|
+
youtube: 'Google',
|
|
442
|
+
yt: 'Google',
|
|
443
|
+
meta: 'Facebook',
|
|
444
|
+
facebook: 'Facebook',
|
|
445
|
+
instagram: 'Facebook',
|
|
446
|
+
ig: 'Facebook',
|
|
447
|
+
igshopping: 'Facebook',
|
|
448
|
+
threads: 'Facebook',
|
|
449
|
+
twitter: 'Twitter',
|
|
450
|
+
snapchat: 'Snapchat',
|
|
451
|
+
pinterest: 'Pinterest',
|
|
452
|
+
bing: 'Bing',
|
|
453
|
+
microsoft: 'Bing',
|
|
454
|
+
tiktok: 'TikTok',
|
|
455
|
+
// ── Paid – Ad Networks ───────────────────────────────────────────────────
|
|
456
|
+
rtbhouse: 'RTB House',
|
|
457
|
+
applovin: 'AppLovin',
|
|
458
|
+
ttd: 'The Trade Desk',
|
|
459
|
+
amazondsp: 'Amazon DSP',
|
|
460
|
+
axon: 'Axon',
|
|
461
|
+
duel: 'Duel',
|
|
462
|
+
// ── Paid – Affiliates ────────────────────────────────────────────────────
|
|
463
|
+
awin: 'Awin',
|
|
464
|
+
'affiliate-cj': 'CJ Affiliate',
|
|
465
|
+
impact: 'Impact',
|
|
466
|
+
rakuten: 'Rakuten',
|
|
467
|
+
superfiliate: 'Superfiliate',
|
|
468
|
+
// ── Organic – AI & Discovery ─────────────────────────────────────────────
|
|
469
|
+
perplexity: 'Perplexity',
|
|
470
|
+
chatgpt: 'ChatGPT',
|
|
471
|
+
'chatgpt.com': 'ChatGPT',
|
|
472
|
+
openai: 'ChatGPT',
|
|
473
|
+
'copilot.com': 'Microsoft Copilot',
|
|
474
|
+
copilot: 'Microsoft Copilot',
|
|
475
|
+
applenews: 'Apple News',
|
|
476
|
+
whatsapp: 'WhatsApp',
|
|
477
|
+
podcast: 'Podcast',
|
|
478
|
+
// ── Retention – Email ────────────────────────────────────────────────────
|
|
479
|
+
mailchimp: 'Mailchimp',
|
|
480
|
+
omnisend: 'Omnisend',
|
|
481
|
+
iterable: 'Iterable',
|
|
482
|
+
listrak: 'Listrak',
|
|
483
|
+
sailthru: 'Sailthru',
|
|
484
|
+
// ── Retention – Push ─────────────────────────────────────────────────────
|
|
485
|
+
pushowl: 'PushOwl',
|
|
486
|
+
// ── Retention – Post-purchase / Payment ──────────────────────────────────
|
|
487
|
+
narvar: 'Narvar',
|
|
488
|
+
shop_app: 'Shop App',
|
|
489
|
+
salesforce: 'Salesforce',
|
|
490
|
+
yotpo: 'Yotpo',
|
|
491
|
+
};
|
|
492
|
+
/**
|
|
493
|
+
* Partial utm_source normalization (startsWith prefix check, lowercase).
|
|
494
|
+
*
|
|
495
|
+
* Checked after exact match so short exact keys (e.g. "ig", "yt") win first.
|
|
496
|
+
*/
|
|
497
|
+
const UTM_SOURCE_PARTIAL = [
|
|
498
|
+
// ── Paid – Social ─────────────────────────────────────────────────────────
|
|
499
|
+
{ prefix: 'tiktok', name: 'TikTok' },
|
|
500
|
+
// ── Paid – Ad Networks ───────────────────────────────────────────────────
|
|
501
|
+
{ prefix: 'criteo', name: 'Criteo' },
|
|
502
|
+
// ── Retention – Email ────────────────────────────────────────────────────
|
|
503
|
+
{ prefix: 'klaviyo', name: 'Klaviyo' },
|
|
504
|
+
// ── Retention – SMS ──────────────────────────────────────────────────────
|
|
505
|
+
{ prefix: 'attentive', name: 'Attentive' },
|
|
506
|
+
{ prefix: 'postscript', name: 'Postscript' },
|
|
507
|
+
// ── Retention – Post-purchase / Payment ──────────────────────────────────
|
|
508
|
+
{ prefix: 'afterpay', name: 'Afterpay' },
|
|
509
|
+
{ prefix: 'klarna', name: 'Klarna' },
|
|
510
|
+
];
|
|
511
|
+
const ORGANIC_SEARCH_ENGINES = [
|
|
512
|
+
{ match: 'google', name: 'Google' },
|
|
513
|
+
{ match: 'bing', name: 'Bing' },
|
|
514
|
+
{ match: 'yahoo', name: 'Yahoo' },
|
|
515
|
+
{ match: 'duckduckgo', name: 'DuckDuckGo' },
|
|
516
|
+
{ match: 'baidu', name: 'Baidu' },
|
|
517
|
+
{ match: 'yandex', name: 'Yandex' },
|
|
518
|
+
{ match: 'brave', name: 'Brave' },
|
|
519
|
+
];
|
|
520
|
+
const KNOWN_REFERRAL_PLATFORMS = [
|
|
521
|
+
{ match: 'facebook', name: 'Facebook' },
|
|
522
|
+
{ match: 'instagram', name: 'Facebook' },
|
|
523
|
+
{ match: 'twitter', name: 'Twitter' },
|
|
524
|
+
{ match: 'x.com', name: 'Twitter' },
|
|
525
|
+
{ match: 'tiktok', name: 'TikTok' },
|
|
526
|
+
{ match: 'pinterest', name: 'Pinterest' },
|
|
527
|
+
{ match: 'linkedin', name: 'LinkedIn' },
|
|
528
|
+
{ match: 'youtube', name: 'YouTube' },
|
|
529
|
+
{ match: 'chatgpt', name: 'ChatGPT' },
|
|
530
|
+
{ match: 'claude', name: 'Claude' },
|
|
531
|
+
{ match: 'perplexity', name: 'Perplexity' },
|
|
532
|
+
{ match: 'shop.app', name: 'Shop App' },
|
|
533
|
+
{ match: 'amazon', name: 'Amazon' },
|
|
534
|
+
{ match: 'attentive', name: 'Attentive' },
|
|
535
|
+
];
|
|
536
|
+
const OFFLINE_TOUCH = 'Blotout_Offline';
|
|
537
|
+
new Set([
|
|
538
|
+
...CLICK_IDS.map((c) => c.label),
|
|
539
|
+
...Object.values(UTM_SOURCE_EXACT),
|
|
540
|
+
...UTM_SOURCE_PARTIAL.map((e) => e.name),
|
|
541
|
+
...ORGANIC_SEARCH_ENGINES.map((e) => `Organic Search - ${e.name}`),
|
|
542
|
+
...KNOWN_REFERRAL_PLATFORMS.map((e) => `Referral - ${e.name}`),
|
|
543
|
+
'Referral - Other',
|
|
544
|
+
'Direct Traffic',
|
|
545
|
+
'Other',
|
|
546
|
+
OFFLINE_TOUCH,
|
|
547
|
+
]);
|
|
548
|
+
|
|
394
549
|
// eslint-disable-next-line @nx/enforce-module-boundaries
|
|
395
550
|
const isConsentEnabled = (consent) => hasUserConsentForProvider(consent, packageName);
|
|
396
551
|
const consent = ({ consentData }) => {
|
|
@@ -537,7 +692,7 @@ const handleTag = ({ data, eventName, manifestVariables, }) => {
|
|
|
537
692
|
|
|
538
693
|
const tag = ({ data, eventName, manifestVariables }) => {
|
|
539
694
|
const payload = {
|
|
540
|
-
sdkVersion: "1.
|
|
695
|
+
sdkVersion: "1.55.0" ,
|
|
541
696
|
};
|
|
542
697
|
if (window.edgeUET && manifestVariables['enableBrowser'] === '1') {
|
|
543
698
|
handleTag({ data, eventName, manifestVariables });
|