@blotoutio/edgetag-sdk-browser 1.53.1 → 1.54.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.
Files changed (2) hide show
  1. package/index.js +156 -1
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -98,6 +98,40 @@
98
98
  return map.set(key, update(currentValue));
99
99
  };
100
100
 
101
+ /**
102
+ * Known ad-network click ID query parameters and the human-readable provider
103
+ * label each one maps to. Used by the CDN worker to resolve `inSessionTouch`
104
+ * and by the analytics API to classify paid-media touch sessions.
105
+ *
106
+ * Keep this list in sync with `defaultParams` in queryParams.ts when new
107
+ * click ID providers are added.
108
+ */
109
+ const CLICK_IDS = [
110
+ { param: 'fbclid', label: 'Facebook' }, // Facebook Ads
111
+ { param: 'gclid', label: 'Google' }, // Google Ads (click)
112
+ { param: 'gbraid', label: 'Google' }, // Google Ads (iOS app)
113
+ { param: 'wbraid', label: 'Google' }, // Google Ads (iOS web)
114
+ { param: 'msclkid', label: 'Bing' }, // Microsoft Bing Ads
115
+ { param: 'ttclid', label: 'TikTok' }, // TikTok Ads
116
+ { param: 'ScCid', label: 'Snapchat' }, // Snapchat Ads
117
+ { param: 'epik', label: 'Pinterest' }, // Pinterest Ads
118
+ { param: 'li_fat_id', label: 'LinkedIn' }, // LinkedIn Ads
119
+ { param: 'twclid', label: 'Twitter' }, // X (Twitter) Ads
120
+ { param: 'rdt_cid', label: 'Reddit' }, // Reddit Ads
121
+ { param: 'aleid', label: 'AppLovin' }, // AppLovin
122
+ { param: 'tabclid', label: 'Taboola' }, // Taboola
123
+ { param: 'obclid', label: 'Outbrain' }, // Outbrain
124
+ { param: 'trybe', label: 'Trybe' }, // Trybe
125
+ { param: '_kx', label: 'Klaviyo' }, // Klaviyo email campaigns
126
+ { param: 'mc_eid', label: 'Mailchimp' }, // Mailchimp email campaigns
127
+ { param: 'ttd_id', label: 'The Trade Desk' }, // The Trade Desk programmatic
128
+ { param: 'evsclid', label: 'EvoSearch' }, // EvoSearch
129
+ { param: 'li_did', label: 'Live Intent' }, // LiveIntent device-level ad
130
+ { param: '_raclid', label: 'Rumble' }, // Rumble Ads
131
+ { param: 'ref_id', label: 'StackAdapt' }, // StackAdapt programmatic
132
+ { param: 'duel_a', label: 'Duel' }, // Duel referral/advocacy
133
+ ];
134
+
101
135
  const expand = (str) => str.split(',').flatMap((entry) => {
102
136
  if (!entry.includes('-')) {
103
137
  return entry;
@@ -829,6 +863,127 @@
829
863
  */
830
864
  const jsonClone = (json) => tryParse(JSON.stringify(json), undefined);
831
865
 
866
+ /**
867
+ * Exact utm_source normalization (lowercase key → canonical name).
868
+ *
869
+ * Use exact match when the key is short, generic, or must not accidentally
870
+ * absorb variant spellings (e.g. "impact" must not match "impact_radius").
871
+ *
872
+ * Ordering: Paid (search/social → ad networks → affiliates) →
873
+ * Organic (AI/discovery) → Retention (email → SMS → push → post-purchase)
874
+ */
875
+ const UTM_SOURCE_EXACT = {
876
+ // ── Paid – Search & Social ────────────────────────────────────────────────
877
+ google: 'Google',
878
+ adwords: 'Google',
879
+ youtube: 'Google',
880
+ yt: 'Google',
881
+ meta: 'Facebook',
882
+ facebook: 'Facebook',
883
+ instagram: 'Facebook',
884
+ ig: 'Facebook',
885
+ igshopping: 'Facebook',
886
+ threads: 'Facebook',
887
+ twitter: 'Twitter',
888
+ snapchat: 'Snapchat',
889
+ pinterest: 'Pinterest',
890
+ bing: 'Bing',
891
+ microsoft: 'Bing',
892
+ tiktok: 'TikTok',
893
+ // ── Paid – Ad Networks ───────────────────────────────────────────────────
894
+ rtbhouse: 'RTB House',
895
+ applovin: 'AppLovin',
896
+ ttd: 'The Trade Desk',
897
+ amazondsp: 'Amazon DSP',
898
+ axon: 'Axon',
899
+ duel: 'Duel',
900
+ // ── Paid – Affiliates ────────────────────────────────────────────────────
901
+ awin: 'Awin',
902
+ 'affiliate-cj': 'CJ Affiliate',
903
+ impact: 'Impact',
904
+ rakuten: 'Rakuten',
905
+ superfiliate: 'Superfiliate',
906
+ // ── Organic – AI & Discovery ─────────────────────────────────────────────
907
+ perplexity: 'Perplexity',
908
+ chatgpt: 'ChatGPT',
909
+ 'chatgpt.com': 'ChatGPT',
910
+ openai: 'ChatGPT',
911
+ 'copilot.com': 'Microsoft Copilot',
912
+ copilot: 'Microsoft Copilot',
913
+ applenews: 'Apple News',
914
+ whatsapp: 'WhatsApp',
915
+ podcast: 'Podcast',
916
+ // ── Retention – Email ────────────────────────────────────────────────────
917
+ mailchimp: 'Mailchimp',
918
+ omnisend: 'Omnisend',
919
+ iterable: 'Iterable',
920
+ listrak: 'Listrak',
921
+ sailthru: 'Sailthru',
922
+ // ── Retention – Push ─────────────────────────────────────────────────────
923
+ pushowl: 'PushOwl',
924
+ // ── Retention – Post-purchase / Payment ──────────────────────────────────
925
+ narvar: 'Narvar',
926
+ shop_app: 'Shop App',
927
+ salesforce: 'Salesforce',
928
+ yotpo: 'Yotpo',
929
+ };
930
+ /**
931
+ * Partial utm_source normalization (startsWith prefix check, lowercase).
932
+ *
933
+ * Checked after exact match so short exact keys (e.g. "ig", "yt") win first.
934
+ */
935
+ const UTM_SOURCE_PARTIAL = [
936
+ // ── Paid – Social ─────────────────────────────────────────────────────────
937
+ { prefix: 'tiktok', name: 'TikTok' },
938
+ // ── Paid – Ad Networks ───────────────────────────────────────────────────
939
+ { prefix: 'criteo', name: 'Criteo' },
940
+ // ── Retention – Email ────────────────────────────────────────────────────
941
+ { prefix: 'klaviyo', name: 'Klaviyo' },
942
+ // ── Retention – SMS ──────────────────────────────────────────────────────
943
+ { prefix: 'attentive', name: 'Attentive' },
944
+ { prefix: 'postscript', name: 'Postscript' },
945
+ // ── Retention – Post-purchase / Payment ──────────────────────────────────
946
+ { prefix: 'afterpay', name: 'Afterpay' },
947
+ { prefix: 'klarna', name: 'Klarna' },
948
+ ];
949
+ const ORGANIC_SEARCH_ENGINES = [
950
+ { match: 'google', name: 'Google' },
951
+ { match: 'bing', name: 'Bing' },
952
+ { match: 'yahoo', name: 'Yahoo' },
953
+ { match: 'duckduckgo', name: 'DuckDuckGo' },
954
+ { match: 'baidu', name: 'Baidu' },
955
+ { match: 'yandex', name: 'Yandex' },
956
+ { match: 'brave', name: 'Brave' },
957
+ ];
958
+ const KNOWN_REFERRAL_PLATFORMS = [
959
+ { match: 'facebook', name: 'Facebook' },
960
+ { match: 'instagram', name: 'Facebook' },
961
+ { match: 'twitter', name: 'Twitter' },
962
+ { match: 'x.com', name: 'Twitter' },
963
+ { match: 'tiktok', name: 'TikTok' },
964
+ { match: 'pinterest', name: 'Pinterest' },
965
+ { match: 'linkedin', name: 'LinkedIn' },
966
+ { match: 'youtube', name: 'YouTube' },
967
+ { match: 'chatgpt', name: 'ChatGPT' },
968
+ { match: 'claude', name: 'Claude' },
969
+ { match: 'perplexity', name: 'Perplexity' },
970
+ { match: 'shop.app', name: 'Shop App' },
971
+ { match: 'amazon', name: 'Amazon' },
972
+ { match: 'attentive', name: 'Attentive' },
973
+ ];
974
+ const OFFLINE_TOUCH = 'Blotout_Offline';
975
+ new Set([
976
+ ...CLICK_IDS.map((c) => c.label),
977
+ ...Object.values(UTM_SOURCE_EXACT),
978
+ ...UTM_SOURCE_PARTIAL.map((e) => e.name),
979
+ ...ORGANIC_SEARCH_ENGINES.map((e) => `Organic Search - ${e.name}`),
980
+ ...KNOWN_REFERRAL_PLATFORMS.map((e) => `Referral - ${e.name}`),
981
+ 'Referral - Other',
982
+ 'Direct Traffic',
983
+ 'Other',
984
+ OFFLINE_TOUCH,
985
+ ]);
986
+
832
987
  // eslint-disable-next-line @nx/enforce-module-boundaries
833
988
  const getGlobalSettings = () => {
834
989
  var _a;
@@ -1311,7 +1466,7 @@
1311
1466
  referrer: getReferrer(destination),
1312
1467
  search: getSearch(destination),
1313
1468
  locale: getLocale(),
1314
- sdkVersion: "1.53.1" ,
1469
+ sdkVersion: "1.54.0" ,
1315
1470
  ...(payload || {}),
1316
1471
  };
1317
1472
  let storage = {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blotoutio/edgetag-sdk-browser",
3
- "version": "1.53.1",
3
+ "version": "1.54.0",
4
4
  "description": "Browser SDK for EdgeTag",
5
5
  "author": "Blotout",
6
6
  "license": "MIT",