@blotoutio/providers-smblead-sdk 1.53.0 → 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 (4) hide show
  1. package/index.cjs.js +155 -0
  2. package/index.js +155 -0
  3. package/index.mjs +155 -0
  4. package/package.json +1 -1
package/index.cjs.js CHANGED
@@ -6,6 +6,40 @@ var STATUS;
6
6
  STATUS["DELETED"] = "DELETED";
7
7
  })(STATUS || (STATUS = {}));
8
8
 
9
+ /**
10
+ * Known ad-network click ID query parameters and the human-readable provider
11
+ * label each one maps to. Used by the CDN worker to resolve `inSessionTouch`
12
+ * and by the analytics API to classify paid-media touch sessions.
13
+ *
14
+ * Keep this list in sync with `defaultParams` in queryParams.ts when new
15
+ * click ID providers are added.
16
+ */
17
+ const CLICK_IDS = [
18
+ { param: 'fbclid', label: 'Facebook' }, // Facebook Ads
19
+ { param: 'gclid', label: 'Google' }, // Google Ads (click)
20
+ { param: 'gbraid', label: 'Google' }, // Google Ads (iOS app)
21
+ { param: 'wbraid', label: 'Google' }, // Google Ads (iOS web)
22
+ { param: 'msclkid', label: 'Bing' }, // Microsoft Bing Ads
23
+ { param: 'ttclid', label: 'TikTok' }, // TikTok Ads
24
+ { param: 'ScCid', label: 'Snapchat' }, // Snapchat Ads
25
+ { param: 'epik', label: 'Pinterest' }, // Pinterest Ads
26
+ { param: 'li_fat_id', label: 'LinkedIn' }, // LinkedIn Ads
27
+ { param: 'twclid', label: 'Twitter' }, // X (Twitter) Ads
28
+ { param: 'rdt_cid', label: 'Reddit' }, // Reddit Ads
29
+ { param: 'aleid', label: 'AppLovin' }, // AppLovin
30
+ { param: 'tabclid', label: 'Taboola' }, // Taboola
31
+ { param: 'obclid', label: 'Outbrain' }, // Outbrain
32
+ { param: 'trybe', label: 'Trybe' }, // Trybe
33
+ { param: '_kx', label: 'Klaviyo' }, // Klaviyo email campaigns
34
+ { param: 'mc_eid', label: 'Mailchimp' }, // Mailchimp email campaigns
35
+ { param: 'ttd_id', label: 'The Trade Desk' }, // The Trade Desk programmatic
36
+ { param: 'evsclid', label: 'EvoSearch' }, // EvoSearch
37
+ { param: 'li_did', label: 'Live Intent' }, // LiveIntent device-level ad
38
+ { param: '_raclid', label: 'Rumble' }, // Rumble Ads
39
+ { param: 'ref_id', label: 'StackAdapt' }, // StackAdapt programmatic
40
+ { param: 'duel_a', label: 'Duel' }, // Duel referral/advocacy
41
+ ];
42
+
9
43
  const expand = (str) => str.split(',').flatMap((entry) => {
10
44
  if (!entry.includes('-')) {
11
45
  return entry;
@@ -362,6 +396,127 @@ const usStates = new Map([
362
396
  ]);
363
397
  new Set([...isoCountries.keys(), ...usStates.keys()]);
364
398
 
399
+ /**
400
+ * Exact utm_source normalization (lowercase key → canonical name).
401
+ *
402
+ * Use exact match when the key is short, generic, or must not accidentally
403
+ * absorb variant spellings (e.g. "impact" must not match "impact_radius").
404
+ *
405
+ * Ordering: Paid (search/social → ad networks → affiliates) →
406
+ * Organic (AI/discovery) → Retention (email → SMS → push → post-purchase)
407
+ */
408
+ const UTM_SOURCE_EXACT = {
409
+ // ── Paid – Search & Social ────────────────────────────────────────────────
410
+ google: 'Google',
411
+ adwords: 'Google',
412
+ youtube: 'Google',
413
+ yt: 'Google',
414
+ meta: 'Facebook',
415
+ facebook: 'Facebook',
416
+ instagram: 'Facebook',
417
+ ig: 'Facebook',
418
+ igshopping: 'Facebook',
419
+ threads: 'Facebook',
420
+ twitter: 'Twitter',
421
+ snapchat: 'Snapchat',
422
+ pinterest: 'Pinterest',
423
+ bing: 'Bing',
424
+ microsoft: 'Bing',
425
+ tiktok: 'TikTok',
426
+ // ── Paid – Ad Networks ───────────────────────────────────────────────────
427
+ rtbhouse: 'RTB House',
428
+ applovin: 'AppLovin',
429
+ ttd: 'The Trade Desk',
430
+ amazondsp: 'Amazon DSP',
431
+ axon: 'Axon',
432
+ duel: 'Duel',
433
+ // ── Paid – Affiliates ────────────────────────────────────────────────────
434
+ awin: 'Awin',
435
+ 'affiliate-cj': 'CJ Affiliate',
436
+ impact: 'Impact',
437
+ rakuten: 'Rakuten',
438
+ superfiliate: 'Superfiliate',
439
+ // ── Organic – AI & Discovery ─────────────────────────────────────────────
440
+ perplexity: 'Perplexity',
441
+ chatgpt: 'ChatGPT',
442
+ 'chatgpt.com': 'ChatGPT',
443
+ openai: 'ChatGPT',
444
+ 'copilot.com': 'Microsoft Copilot',
445
+ copilot: 'Microsoft Copilot',
446
+ applenews: 'Apple News',
447
+ whatsapp: 'WhatsApp',
448
+ podcast: 'Podcast',
449
+ // ── Retention – Email ────────────────────────────────────────────────────
450
+ mailchimp: 'Mailchimp',
451
+ omnisend: 'Omnisend',
452
+ iterable: 'Iterable',
453
+ listrak: 'Listrak',
454
+ sailthru: 'Sailthru',
455
+ // ── Retention – Push ─────────────────────────────────────────────────────
456
+ pushowl: 'PushOwl',
457
+ // ── Retention – Post-purchase / Payment ──────────────────────────────────
458
+ narvar: 'Narvar',
459
+ shop_app: 'Shop App',
460
+ salesforce: 'Salesforce',
461
+ yotpo: 'Yotpo',
462
+ };
463
+ /**
464
+ * Partial utm_source normalization (startsWith prefix check, lowercase).
465
+ *
466
+ * Checked after exact match so short exact keys (e.g. "ig", "yt") win first.
467
+ */
468
+ const UTM_SOURCE_PARTIAL = [
469
+ // ── Paid – Social ─────────────────────────────────────────────────────────
470
+ { prefix: 'tiktok', name: 'TikTok' },
471
+ // ── Paid – Ad Networks ───────────────────────────────────────────────────
472
+ { prefix: 'criteo', name: 'Criteo' },
473
+ // ── Retention – Email ────────────────────────────────────────────────────
474
+ { prefix: 'klaviyo', name: 'Klaviyo' },
475
+ // ── Retention – SMS ──────────────────────────────────────────────────────
476
+ { prefix: 'attentive', name: 'Attentive' },
477
+ { prefix: 'postscript', name: 'Postscript' },
478
+ // ── Retention – Post-purchase / Payment ──────────────────────────────────
479
+ { prefix: 'afterpay', name: 'Afterpay' },
480
+ { prefix: 'klarna', name: 'Klarna' },
481
+ ];
482
+ const ORGANIC_SEARCH_ENGINES = [
483
+ { match: 'google', name: 'Google' },
484
+ { match: 'bing', name: 'Bing' },
485
+ { match: 'yahoo', name: 'Yahoo' },
486
+ { match: 'duckduckgo', name: 'DuckDuckGo' },
487
+ { match: 'baidu', name: 'Baidu' },
488
+ { match: 'yandex', name: 'Yandex' },
489
+ { match: 'brave', name: 'Brave' },
490
+ ];
491
+ const KNOWN_REFERRAL_PLATFORMS = [
492
+ { match: 'facebook', name: 'Facebook' },
493
+ { match: 'instagram', name: 'Facebook' },
494
+ { match: 'twitter', name: 'Twitter' },
495
+ { match: 'x.com', name: 'Twitter' },
496
+ { match: 'tiktok', name: 'TikTok' },
497
+ { match: 'pinterest', name: 'Pinterest' },
498
+ { match: 'linkedin', name: 'LinkedIn' },
499
+ { match: 'youtube', name: 'YouTube' },
500
+ { match: 'chatgpt', name: 'ChatGPT' },
501
+ { match: 'claude', name: 'Claude' },
502
+ { match: 'perplexity', name: 'Perplexity' },
503
+ { match: 'shop.app', name: 'Shop App' },
504
+ { match: 'amazon', name: 'Amazon' },
505
+ { match: 'attentive', name: 'Attentive' },
506
+ ];
507
+ const OFFLINE_TOUCH = 'Blotout_Offline';
508
+ new Set([
509
+ ...CLICK_IDS.map((c) => c.label),
510
+ ...Object.values(UTM_SOURCE_EXACT),
511
+ ...UTM_SOURCE_PARTIAL.map((e) => e.name),
512
+ ...ORGANIC_SEARCH_ENGINES.map((e) => `Organic Search - ${e.name}`),
513
+ ...KNOWN_REFERRAL_PLATFORMS.map((e) => `Referral - ${e.name}`),
514
+ 'Referral - Other',
515
+ 'Direct Traffic',
516
+ 'Other',
517
+ OFFLINE_TOUCH,
518
+ ]);
519
+
365
520
  const packageName = 'smblead';
366
521
 
367
522
  const init = ({ manifest }) => {
package/index.js CHANGED
@@ -7,6 +7,40 @@ var ProvidersSmbleadSdk = (function () {
7
7
  STATUS["DELETED"] = "DELETED";
8
8
  })(STATUS || (STATUS = {}));
9
9
 
10
+ /**
11
+ * Known ad-network click ID query parameters and the human-readable provider
12
+ * label each one maps to. Used by the CDN worker to resolve `inSessionTouch`
13
+ * and by the analytics API to classify paid-media touch sessions.
14
+ *
15
+ * Keep this list in sync with `defaultParams` in queryParams.ts when new
16
+ * click ID providers are added.
17
+ */
18
+ const CLICK_IDS = [
19
+ { param: 'fbclid', label: 'Facebook' }, // Facebook Ads
20
+ { param: 'gclid', label: 'Google' }, // Google Ads (click)
21
+ { param: 'gbraid', label: 'Google' }, // Google Ads (iOS app)
22
+ { param: 'wbraid', label: 'Google' }, // Google Ads (iOS web)
23
+ { param: 'msclkid', label: 'Bing' }, // Microsoft Bing Ads
24
+ { param: 'ttclid', label: 'TikTok' }, // TikTok Ads
25
+ { param: 'ScCid', label: 'Snapchat' }, // Snapchat Ads
26
+ { param: 'epik', label: 'Pinterest' }, // Pinterest Ads
27
+ { param: 'li_fat_id', label: 'LinkedIn' }, // LinkedIn Ads
28
+ { param: 'twclid', label: 'Twitter' }, // X (Twitter) Ads
29
+ { param: 'rdt_cid', label: 'Reddit' }, // Reddit Ads
30
+ { param: 'aleid', label: 'AppLovin' }, // AppLovin
31
+ { param: 'tabclid', label: 'Taboola' }, // Taboola
32
+ { param: 'obclid', label: 'Outbrain' }, // Outbrain
33
+ { param: 'trybe', label: 'Trybe' }, // Trybe
34
+ { param: '_kx', label: 'Klaviyo' }, // Klaviyo email campaigns
35
+ { param: 'mc_eid', label: 'Mailchimp' }, // Mailchimp email campaigns
36
+ { param: 'ttd_id', label: 'The Trade Desk' }, // The Trade Desk programmatic
37
+ { param: 'evsclid', label: 'EvoSearch' }, // EvoSearch
38
+ { param: 'li_did', label: 'Live Intent' }, // LiveIntent device-level ad
39
+ { param: '_raclid', label: 'Rumble' }, // Rumble Ads
40
+ { param: 'ref_id', label: 'StackAdapt' }, // StackAdapt programmatic
41
+ { param: 'duel_a', label: 'Duel' }, // Duel referral/advocacy
42
+ ];
43
+
10
44
  const expand = (str) => str.split(',').flatMap((entry) => {
11
45
  if (!entry.includes('-')) {
12
46
  return entry;
@@ -363,6 +397,127 @@ var ProvidersSmbleadSdk = (function () {
363
397
  ]);
364
398
  new Set([...isoCountries.keys(), ...usStates.keys()]);
365
399
 
400
+ /**
401
+ * Exact utm_source normalization (lowercase key → canonical name).
402
+ *
403
+ * Use exact match when the key is short, generic, or must not accidentally
404
+ * absorb variant spellings (e.g. "impact" must not match "impact_radius").
405
+ *
406
+ * Ordering: Paid (search/social → ad networks → affiliates) →
407
+ * Organic (AI/discovery) → Retention (email → SMS → push → post-purchase)
408
+ */
409
+ const UTM_SOURCE_EXACT = {
410
+ // ── Paid – Search & Social ────────────────────────────────────────────────
411
+ google: 'Google',
412
+ adwords: 'Google',
413
+ youtube: 'Google',
414
+ yt: 'Google',
415
+ meta: 'Facebook',
416
+ facebook: 'Facebook',
417
+ instagram: 'Facebook',
418
+ ig: 'Facebook',
419
+ igshopping: 'Facebook',
420
+ threads: 'Facebook',
421
+ twitter: 'Twitter',
422
+ snapchat: 'Snapchat',
423
+ pinterest: 'Pinterest',
424
+ bing: 'Bing',
425
+ microsoft: 'Bing',
426
+ tiktok: 'TikTok',
427
+ // ── Paid – Ad Networks ───────────────────────────────────────────────────
428
+ rtbhouse: 'RTB House',
429
+ applovin: 'AppLovin',
430
+ ttd: 'The Trade Desk',
431
+ amazondsp: 'Amazon DSP',
432
+ axon: 'Axon',
433
+ duel: 'Duel',
434
+ // ── Paid – Affiliates ────────────────────────────────────────────────────
435
+ awin: 'Awin',
436
+ 'affiliate-cj': 'CJ Affiliate',
437
+ impact: 'Impact',
438
+ rakuten: 'Rakuten',
439
+ superfiliate: 'Superfiliate',
440
+ // ── Organic – AI & Discovery ─────────────────────────────────────────────
441
+ perplexity: 'Perplexity',
442
+ chatgpt: 'ChatGPT',
443
+ 'chatgpt.com': 'ChatGPT',
444
+ openai: 'ChatGPT',
445
+ 'copilot.com': 'Microsoft Copilot',
446
+ copilot: 'Microsoft Copilot',
447
+ applenews: 'Apple News',
448
+ whatsapp: 'WhatsApp',
449
+ podcast: 'Podcast',
450
+ // ── Retention – Email ────────────────────────────────────────────────────
451
+ mailchimp: 'Mailchimp',
452
+ omnisend: 'Omnisend',
453
+ iterable: 'Iterable',
454
+ listrak: 'Listrak',
455
+ sailthru: 'Sailthru',
456
+ // ── Retention – Push ─────────────────────────────────────────────────────
457
+ pushowl: 'PushOwl',
458
+ // ── Retention – Post-purchase / Payment ──────────────────────────────────
459
+ narvar: 'Narvar',
460
+ shop_app: 'Shop App',
461
+ salesforce: 'Salesforce',
462
+ yotpo: 'Yotpo',
463
+ };
464
+ /**
465
+ * Partial utm_source normalization (startsWith prefix check, lowercase).
466
+ *
467
+ * Checked after exact match so short exact keys (e.g. "ig", "yt") win first.
468
+ */
469
+ const UTM_SOURCE_PARTIAL = [
470
+ // ── Paid – Social ─────────────────────────────────────────────────────────
471
+ { prefix: 'tiktok', name: 'TikTok' },
472
+ // ── Paid – Ad Networks ───────────────────────────────────────────────────
473
+ { prefix: 'criteo', name: 'Criteo' },
474
+ // ── Retention – Email ────────────────────────────────────────────────────
475
+ { prefix: 'klaviyo', name: 'Klaviyo' },
476
+ // ── Retention – SMS ──────────────────────────────────────────────────────
477
+ { prefix: 'attentive', name: 'Attentive' },
478
+ { prefix: 'postscript', name: 'Postscript' },
479
+ // ── Retention – Post-purchase / Payment ──────────────────────────────────
480
+ { prefix: 'afterpay', name: 'Afterpay' },
481
+ { prefix: 'klarna', name: 'Klarna' },
482
+ ];
483
+ const ORGANIC_SEARCH_ENGINES = [
484
+ { match: 'google', name: 'Google' },
485
+ { match: 'bing', name: 'Bing' },
486
+ { match: 'yahoo', name: 'Yahoo' },
487
+ { match: 'duckduckgo', name: 'DuckDuckGo' },
488
+ { match: 'baidu', name: 'Baidu' },
489
+ { match: 'yandex', name: 'Yandex' },
490
+ { match: 'brave', name: 'Brave' },
491
+ ];
492
+ const KNOWN_REFERRAL_PLATFORMS = [
493
+ { match: 'facebook', name: 'Facebook' },
494
+ { match: 'instagram', name: 'Facebook' },
495
+ { match: 'twitter', name: 'Twitter' },
496
+ { match: 'x.com', name: 'Twitter' },
497
+ { match: 'tiktok', name: 'TikTok' },
498
+ { match: 'pinterest', name: 'Pinterest' },
499
+ { match: 'linkedin', name: 'LinkedIn' },
500
+ { match: 'youtube', name: 'YouTube' },
501
+ { match: 'chatgpt', name: 'ChatGPT' },
502
+ { match: 'claude', name: 'Claude' },
503
+ { match: 'perplexity', name: 'Perplexity' },
504
+ { match: 'shop.app', name: 'Shop App' },
505
+ { match: 'amazon', name: 'Amazon' },
506
+ { match: 'attentive', name: 'Attentive' },
507
+ ];
508
+ const OFFLINE_TOUCH = 'Blotout_Offline';
509
+ new Set([
510
+ ...CLICK_IDS.map((c) => c.label),
511
+ ...Object.values(UTM_SOURCE_EXACT),
512
+ ...UTM_SOURCE_PARTIAL.map((e) => e.name),
513
+ ...ORGANIC_SEARCH_ENGINES.map((e) => `Organic Search - ${e.name}`),
514
+ ...KNOWN_REFERRAL_PLATFORMS.map((e) => `Referral - ${e.name}`),
515
+ 'Referral - Other',
516
+ 'Direct Traffic',
517
+ 'Other',
518
+ OFFLINE_TOUCH,
519
+ ]);
520
+
366
521
  const packageName = 'smblead';
367
522
 
368
523
  const init = ({ manifest }) => {
package/index.mjs CHANGED
@@ -4,6 +4,40 @@ var STATUS;
4
4
  STATUS["DELETED"] = "DELETED";
5
5
  })(STATUS || (STATUS = {}));
6
6
 
7
+ /**
8
+ * Known ad-network click ID query parameters and the human-readable provider
9
+ * label each one maps to. Used by the CDN worker to resolve `inSessionTouch`
10
+ * and by the analytics API to classify paid-media touch sessions.
11
+ *
12
+ * Keep this list in sync with `defaultParams` in queryParams.ts when new
13
+ * click ID providers are added.
14
+ */
15
+ const CLICK_IDS = [
16
+ { param: 'fbclid', label: 'Facebook' }, // Facebook Ads
17
+ { param: 'gclid', label: 'Google' }, // Google Ads (click)
18
+ { param: 'gbraid', label: 'Google' }, // Google Ads (iOS app)
19
+ { param: 'wbraid', label: 'Google' }, // Google Ads (iOS web)
20
+ { param: 'msclkid', label: 'Bing' }, // Microsoft Bing Ads
21
+ { param: 'ttclid', label: 'TikTok' }, // TikTok Ads
22
+ { param: 'ScCid', label: 'Snapchat' }, // Snapchat Ads
23
+ { param: 'epik', label: 'Pinterest' }, // Pinterest Ads
24
+ { param: 'li_fat_id', label: 'LinkedIn' }, // LinkedIn Ads
25
+ { param: 'twclid', label: 'Twitter' }, // X (Twitter) Ads
26
+ { param: 'rdt_cid', label: 'Reddit' }, // Reddit Ads
27
+ { param: 'aleid', label: 'AppLovin' }, // AppLovin
28
+ { param: 'tabclid', label: 'Taboola' }, // Taboola
29
+ { param: 'obclid', label: 'Outbrain' }, // Outbrain
30
+ { param: 'trybe', label: 'Trybe' }, // Trybe
31
+ { param: '_kx', label: 'Klaviyo' }, // Klaviyo email campaigns
32
+ { param: 'mc_eid', label: 'Mailchimp' }, // Mailchimp email campaigns
33
+ { param: 'ttd_id', label: 'The Trade Desk' }, // The Trade Desk programmatic
34
+ { param: 'evsclid', label: 'EvoSearch' }, // EvoSearch
35
+ { param: 'li_did', label: 'Live Intent' }, // LiveIntent device-level ad
36
+ { param: '_raclid', label: 'Rumble' }, // Rumble Ads
37
+ { param: 'ref_id', label: 'StackAdapt' }, // StackAdapt programmatic
38
+ { param: 'duel_a', label: 'Duel' }, // Duel referral/advocacy
39
+ ];
40
+
7
41
  const expand = (str) => str.split(',').flatMap((entry) => {
8
42
  if (!entry.includes('-')) {
9
43
  return entry;
@@ -360,6 +394,127 @@ const usStates = new Map([
360
394
  ]);
361
395
  new Set([...isoCountries.keys(), ...usStates.keys()]);
362
396
 
397
+ /**
398
+ * Exact utm_source normalization (lowercase key → canonical name).
399
+ *
400
+ * Use exact match when the key is short, generic, or must not accidentally
401
+ * absorb variant spellings (e.g. "impact" must not match "impact_radius").
402
+ *
403
+ * Ordering: Paid (search/social → ad networks → affiliates) →
404
+ * Organic (AI/discovery) → Retention (email → SMS → push → post-purchase)
405
+ */
406
+ const UTM_SOURCE_EXACT = {
407
+ // ── Paid – Search & Social ────────────────────────────────────────────────
408
+ google: 'Google',
409
+ adwords: 'Google',
410
+ youtube: 'Google',
411
+ yt: 'Google',
412
+ meta: 'Facebook',
413
+ facebook: 'Facebook',
414
+ instagram: 'Facebook',
415
+ ig: 'Facebook',
416
+ igshopping: 'Facebook',
417
+ threads: 'Facebook',
418
+ twitter: 'Twitter',
419
+ snapchat: 'Snapchat',
420
+ pinterest: 'Pinterest',
421
+ bing: 'Bing',
422
+ microsoft: 'Bing',
423
+ tiktok: 'TikTok',
424
+ // ── Paid – Ad Networks ───────────────────────────────────────────────────
425
+ rtbhouse: 'RTB House',
426
+ applovin: 'AppLovin',
427
+ ttd: 'The Trade Desk',
428
+ amazondsp: 'Amazon DSP',
429
+ axon: 'Axon',
430
+ duel: 'Duel',
431
+ // ── Paid – Affiliates ────────────────────────────────────────────────────
432
+ awin: 'Awin',
433
+ 'affiliate-cj': 'CJ Affiliate',
434
+ impact: 'Impact',
435
+ rakuten: 'Rakuten',
436
+ superfiliate: 'Superfiliate',
437
+ // ── Organic – AI & Discovery ─────────────────────────────────────────────
438
+ perplexity: 'Perplexity',
439
+ chatgpt: 'ChatGPT',
440
+ 'chatgpt.com': 'ChatGPT',
441
+ openai: 'ChatGPT',
442
+ 'copilot.com': 'Microsoft Copilot',
443
+ copilot: 'Microsoft Copilot',
444
+ applenews: 'Apple News',
445
+ whatsapp: 'WhatsApp',
446
+ podcast: 'Podcast',
447
+ // ── Retention – Email ────────────────────────────────────────────────────
448
+ mailchimp: 'Mailchimp',
449
+ omnisend: 'Omnisend',
450
+ iterable: 'Iterable',
451
+ listrak: 'Listrak',
452
+ sailthru: 'Sailthru',
453
+ // ── Retention – Push ─────────────────────────────────────────────────────
454
+ pushowl: 'PushOwl',
455
+ // ── Retention – Post-purchase / Payment ──────────────────────────────────
456
+ narvar: 'Narvar',
457
+ shop_app: 'Shop App',
458
+ salesforce: 'Salesforce',
459
+ yotpo: 'Yotpo',
460
+ };
461
+ /**
462
+ * Partial utm_source normalization (startsWith prefix check, lowercase).
463
+ *
464
+ * Checked after exact match so short exact keys (e.g. "ig", "yt") win first.
465
+ */
466
+ const UTM_SOURCE_PARTIAL = [
467
+ // ── Paid – Social ─────────────────────────────────────────────────────────
468
+ { prefix: 'tiktok', name: 'TikTok' },
469
+ // ── Paid – Ad Networks ───────────────────────────────────────────────────
470
+ { prefix: 'criteo', name: 'Criteo' },
471
+ // ── Retention – Email ────────────────────────────────────────────────────
472
+ { prefix: 'klaviyo', name: 'Klaviyo' },
473
+ // ── Retention – SMS ──────────────────────────────────────────────────────
474
+ { prefix: 'attentive', name: 'Attentive' },
475
+ { prefix: 'postscript', name: 'Postscript' },
476
+ // ── Retention – Post-purchase / Payment ──────────────────────────────────
477
+ { prefix: 'afterpay', name: 'Afterpay' },
478
+ { prefix: 'klarna', name: 'Klarna' },
479
+ ];
480
+ const ORGANIC_SEARCH_ENGINES = [
481
+ { match: 'google', name: 'Google' },
482
+ { match: 'bing', name: 'Bing' },
483
+ { match: 'yahoo', name: 'Yahoo' },
484
+ { match: 'duckduckgo', name: 'DuckDuckGo' },
485
+ { match: 'baidu', name: 'Baidu' },
486
+ { match: 'yandex', name: 'Yandex' },
487
+ { match: 'brave', name: 'Brave' },
488
+ ];
489
+ const KNOWN_REFERRAL_PLATFORMS = [
490
+ { match: 'facebook', name: 'Facebook' },
491
+ { match: 'instagram', name: 'Facebook' },
492
+ { match: 'twitter', name: 'Twitter' },
493
+ { match: 'x.com', name: 'Twitter' },
494
+ { match: 'tiktok', name: 'TikTok' },
495
+ { match: 'pinterest', name: 'Pinterest' },
496
+ { match: 'linkedin', name: 'LinkedIn' },
497
+ { match: 'youtube', name: 'YouTube' },
498
+ { match: 'chatgpt', name: 'ChatGPT' },
499
+ { match: 'claude', name: 'Claude' },
500
+ { match: 'perplexity', name: 'Perplexity' },
501
+ { match: 'shop.app', name: 'Shop App' },
502
+ { match: 'amazon', name: 'Amazon' },
503
+ { match: 'attentive', name: 'Attentive' },
504
+ ];
505
+ const OFFLINE_TOUCH = 'Blotout_Offline';
506
+ new Set([
507
+ ...CLICK_IDS.map((c) => c.label),
508
+ ...Object.values(UTM_SOURCE_EXACT),
509
+ ...UTM_SOURCE_PARTIAL.map((e) => e.name),
510
+ ...ORGANIC_SEARCH_ENGINES.map((e) => `Organic Search - ${e.name}`),
511
+ ...KNOWN_REFERRAL_PLATFORMS.map((e) => `Referral - ${e.name}`),
512
+ 'Referral - Other',
513
+ 'Direct Traffic',
514
+ 'Other',
515
+ OFFLINE_TOUCH,
516
+ ]);
517
+
363
518
  const packageName = 'smblead';
364
519
 
365
520
  const init = ({ manifest }) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blotoutio/providers-smblead-sdk",
3
- "version": "1.53.0",
3
+ "version": "1.54.0",
4
4
  "description": "CustomersAI Browser SDK for EdgeTag",
5
5
  "author": "Blotout",
6
6
  "license": "MIT",