@blotoutio/providers-google-ads-clicks-sdk 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 (4) hide show
  1. package/index.cjs.js +156 -1
  2. package/index.js +156 -1
  3. package/index.mjs +156 -1
  4. package/package.json +1 -1
package/index.cjs.js CHANGED
@@ -44,6 +44,40 @@ const upsert = (map, key, update, createDefault) => {
44
44
  return map.set(key, update(currentValue));
45
45
  };
46
46
 
47
+ /**
48
+ * Known ad-network click ID query parameters and the human-readable provider
49
+ * label each one maps to. Used by the CDN worker to resolve `inSessionTouch`
50
+ * and by the analytics API to classify paid-media touch sessions.
51
+ *
52
+ * Keep this list in sync with `defaultParams` in queryParams.ts when new
53
+ * click ID providers are added.
54
+ */
55
+ const CLICK_IDS = [
56
+ { param: 'fbclid', label: 'Facebook' }, // Facebook Ads
57
+ { param: 'gclid', label: 'Google' }, // Google Ads (click)
58
+ { param: 'gbraid', label: 'Google' }, // Google Ads (iOS app)
59
+ { param: 'wbraid', label: 'Google' }, // Google Ads (iOS web)
60
+ { param: 'msclkid', label: 'Bing' }, // Microsoft Bing Ads
61
+ { param: 'ttclid', label: 'TikTok' }, // TikTok Ads
62
+ { param: 'ScCid', label: 'Snapchat' }, // Snapchat Ads
63
+ { param: 'epik', label: 'Pinterest' }, // Pinterest Ads
64
+ { param: 'li_fat_id', label: 'LinkedIn' }, // LinkedIn Ads
65
+ { param: 'twclid', label: 'Twitter' }, // X (Twitter) Ads
66
+ { param: 'rdt_cid', label: 'Reddit' }, // Reddit Ads
67
+ { param: 'aleid', label: 'AppLovin' }, // AppLovin
68
+ { param: 'tabclid', label: 'Taboola' }, // Taboola
69
+ { param: 'obclid', label: 'Outbrain' }, // Outbrain
70
+ { param: 'trybe', label: 'Trybe' }, // Trybe
71
+ { param: '_kx', label: 'Klaviyo' }, // Klaviyo email campaigns
72
+ { param: 'mc_eid', label: 'Mailchimp' }, // Mailchimp email campaigns
73
+ { param: 'ttd_id', label: 'The Trade Desk' }, // The Trade Desk programmatic
74
+ { param: 'evsclid', label: 'EvoSearch' }, // EvoSearch
75
+ { param: 'li_did', label: 'Live Intent' }, // LiveIntent device-level ad
76
+ { param: '_raclid', label: 'Rumble' }, // Rumble Ads
77
+ { param: 'ref_id', label: 'StackAdapt' }, // StackAdapt programmatic
78
+ { param: 'duel_a', label: 'Duel' }, // Duel referral/advocacy
79
+ ];
80
+
47
81
  const addDaysToDate = (date, days) => {
48
82
  const newDate = new Date(date);
49
83
  newDate.setDate(newDate.getDate() + days);
@@ -418,6 +452,127 @@ const usStates = new Map([
418
452
  ]);
419
453
  new Set([...isoCountries.keys(), ...usStates.keys()]);
420
454
 
455
+ /**
456
+ * Exact utm_source normalization (lowercase key → canonical name).
457
+ *
458
+ * Use exact match when the key is short, generic, or must not accidentally
459
+ * absorb variant spellings (e.g. "impact" must not match "impact_radius").
460
+ *
461
+ * Ordering: Paid (search/social → ad networks → affiliates) →
462
+ * Organic (AI/discovery) → Retention (email → SMS → push → post-purchase)
463
+ */
464
+ const UTM_SOURCE_EXACT = {
465
+ // ── Paid – Search & Social ────────────────────────────────────────────────
466
+ google: 'Google',
467
+ adwords: 'Google',
468
+ youtube: 'Google',
469
+ yt: 'Google',
470
+ meta: 'Facebook',
471
+ facebook: 'Facebook',
472
+ instagram: 'Facebook',
473
+ ig: 'Facebook',
474
+ igshopping: 'Facebook',
475
+ threads: 'Facebook',
476
+ twitter: 'Twitter',
477
+ snapchat: 'Snapchat',
478
+ pinterest: 'Pinterest',
479
+ bing: 'Bing',
480
+ microsoft: 'Bing',
481
+ tiktok: 'TikTok',
482
+ // ── Paid – Ad Networks ───────────────────────────────────────────────────
483
+ rtbhouse: 'RTB House',
484
+ applovin: 'AppLovin',
485
+ ttd: 'The Trade Desk',
486
+ amazondsp: 'Amazon DSP',
487
+ axon: 'Axon',
488
+ duel: 'Duel',
489
+ // ── Paid – Affiliates ────────────────────────────────────────────────────
490
+ awin: 'Awin',
491
+ 'affiliate-cj': 'CJ Affiliate',
492
+ impact: 'Impact',
493
+ rakuten: 'Rakuten',
494
+ superfiliate: 'Superfiliate',
495
+ // ── Organic – AI & Discovery ─────────────────────────────────────────────
496
+ perplexity: 'Perplexity',
497
+ chatgpt: 'ChatGPT',
498
+ 'chatgpt.com': 'ChatGPT',
499
+ openai: 'ChatGPT',
500
+ 'copilot.com': 'Microsoft Copilot',
501
+ copilot: 'Microsoft Copilot',
502
+ applenews: 'Apple News',
503
+ whatsapp: 'WhatsApp',
504
+ podcast: 'Podcast',
505
+ // ── Retention – Email ────────────────────────────────────────────────────
506
+ mailchimp: 'Mailchimp',
507
+ omnisend: 'Omnisend',
508
+ iterable: 'Iterable',
509
+ listrak: 'Listrak',
510
+ sailthru: 'Sailthru',
511
+ // ── Retention – Push ─────────────────────────────────────────────────────
512
+ pushowl: 'PushOwl',
513
+ // ── Retention – Post-purchase / Payment ──────────────────────────────────
514
+ narvar: 'Narvar',
515
+ shop_app: 'Shop App',
516
+ salesforce: 'Salesforce',
517
+ yotpo: 'Yotpo',
518
+ };
519
+ /**
520
+ * Partial utm_source normalization (startsWith prefix check, lowercase).
521
+ *
522
+ * Checked after exact match so short exact keys (e.g. "ig", "yt") win first.
523
+ */
524
+ const UTM_SOURCE_PARTIAL = [
525
+ // ── Paid – Social ─────────────────────────────────────────────────────────
526
+ { prefix: 'tiktok', name: 'TikTok' },
527
+ // ── Paid – Ad Networks ───────────────────────────────────────────────────
528
+ { prefix: 'criteo', name: 'Criteo' },
529
+ // ── Retention – Email ────────────────────────────────────────────────────
530
+ { prefix: 'klaviyo', name: 'Klaviyo' },
531
+ // ── Retention – SMS ──────────────────────────────────────────────────────
532
+ { prefix: 'attentive', name: 'Attentive' },
533
+ { prefix: 'postscript', name: 'Postscript' },
534
+ // ── Retention – Post-purchase / Payment ──────────────────────────────────
535
+ { prefix: 'afterpay', name: 'Afterpay' },
536
+ { prefix: 'klarna', name: 'Klarna' },
537
+ ];
538
+ const ORGANIC_SEARCH_ENGINES = [
539
+ { match: 'google', name: 'Google' },
540
+ { match: 'bing', name: 'Bing' },
541
+ { match: 'yahoo', name: 'Yahoo' },
542
+ { match: 'duckduckgo', name: 'DuckDuckGo' },
543
+ { match: 'baidu', name: 'Baidu' },
544
+ { match: 'yandex', name: 'Yandex' },
545
+ { match: 'brave', name: 'Brave' },
546
+ ];
547
+ const KNOWN_REFERRAL_PLATFORMS = [
548
+ { match: 'facebook', name: 'Facebook' },
549
+ { match: 'instagram', name: 'Facebook' },
550
+ { match: 'twitter', name: 'Twitter' },
551
+ { match: 'x.com', name: 'Twitter' },
552
+ { match: 'tiktok', name: 'TikTok' },
553
+ { match: 'pinterest', name: 'Pinterest' },
554
+ { match: 'linkedin', name: 'LinkedIn' },
555
+ { match: 'youtube', name: 'YouTube' },
556
+ { match: 'chatgpt', name: 'ChatGPT' },
557
+ { match: 'claude', name: 'Claude' },
558
+ { match: 'perplexity', name: 'Perplexity' },
559
+ { match: 'shop.app', name: 'Shop App' },
560
+ { match: 'amazon', name: 'Amazon' },
561
+ { match: 'attentive', name: 'Attentive' },
562
+ ];
563
+ const OFFLINE_TOUCH = 'Blotout_Offline';
564
+ new Set([
565
+ ...CLICK_IDS.map((c) => c.label),
566
+ ...Object.values(UTM_SOURCE_EXACT),
567
+ ...UTM_SOURCE_PARTIAL.map((e) => e.name),
568
+ ...ORGANIC_SEARCH_ENGINES.map((e) => `Organic Search - ${e.name}`),
569
+ ...KNOWN_REFERRAL_PLATFORMS.map((e) => `Referral - ${e.name}`),
570
+ 'Referral - Other',
571
+ 'Direct Traffic',
572
+ 'Other',
573
+ OFFLINE_TOUCH,
574
+ ]);
575
+
421
576
  const getGoogleConsent = (consentData) => {
422
577
  const gadsConsent = hasUserConsentForProvider(consentData, 'googleAdsClicks');
423
578
  return {
@@ -760,7 +915,7 @@ const tag = ({ data, eventName, manifestVariables, destination, pageUrl, }) => {
760
915
  var _a;
761
916
  const result = {
762
917
  isFired: false,
763
- sdkVersion: "1.53.1" ,
918
+ sdkVersion: "1.54.0" ,
764
919
  };
765
920
  if (!eventName || !window.gtag || !(manifestVariables === null || manifestVariables === void 0 ? void 0 : manifestVariables['tagId'])) {
766
921
  return result;
package/index.js CHANGED
@@ -45,6 +45,40 @@ var ProvidersGoogleAdsClicksSdk = (function () {
45
45
  return map.set(key, update(currentValue));
46
46
  };
47
47
 
48
+ /**
49
+ * Known ad-network click ID query parameters and the human-readable provider
50
+ * label each one maps to. Used by the CDN worker to resolve `inSessionTouch`
51
+ * and by the analytics API to classify paid-media touch sessions.
52
+ *
53
+ * Keep this list in sync with `defaultParams` in queryParams.ts when new
54
+ * click ID providers are added.
55
+ */
56
+ const CLICK_IDS = [
57
+ { param: 'fbclid', label: 'Facebook' }, // Facebook Ads
58
+ { param: 'gclid', label: 'Google' }, // Google Ads (click)
59
+ { param: 'gbraid', label: 'Google' }, // Google Ads (iOS app)
60
+ { param: 'wbraid', label: 'Google' }, // Google Ads (iOS web)
61
+ { param: 'msclkid', label: 'Bing' }, // Microsoft Bing Ads
62
+ { param: 'ttclid', label: 'TikTok' }, // TikTok Ads
63
+ { param: 'ScCid', label: 'Snapchat' }, // Snapchat Ads
64
+ { param: 'epik', label: 'Pinterest' }, // Pinterest Ads
65
+ { param: 'li_fat_id', label: 'LinkedIn' }, // LinkedIn Ads
66
+ { param: 'twclid', label: 'Twitter' }, // X (Twitter) Ads
67
+ { param: 'rdt_cid', label: 'Reddit' }, // Reddit Ads
68
+ { param: 'aleid', label: 'AppLovin' }, // AppLovin
69
+ { param: 'tabclid', label: 'Taboola' }, // Taboola
70
+ { param: 'obclid', label: 'Outbrain' }, // Outbrain
71
+ { param: 'trybe', label: 'Trybe' }, // Trybe
72
+ { param: '_kx', label: 'Klaviyo' }, // Klaviyo email campaigns
73
+ { param: 'mc_eid', label: 'Mailchimp' }, // Mailchimp email campaigns
74
+ { param: 'ttd_id', label: 'The Trade Desk' }, // The Trade Desk programmatic
75
+ { param: 'evsclid', label: 'EvoSearch' }, // EvoSearch
76
+ { param: 'li_did', label: 'Live Intent' }, // LiveIntent device-level ad
77
+ { param: '_raclid', label: 'Rumble' }, // Rumble Ads
78
+ { param: 'ref_id', label: 'StackAdapt' }, // StackAdapt programmatic
79
+ { param: 'duel_a', label: 'Duel' }, // Duel referral/advocacy
80
+ ];
81
+
48
82
  const addDaysToDate = (date, days) => {
49
83
  const newDate = new Date(date);
50
84
  newDate.setDate(newDate.getDate() + days);
@@ -419,6 +453,127 @@ var ProvidersGoogleAdsClicksSdk = (function () {
419
453
  ]);
420
454
  new Set([...isoCountries.keys(), ...usStates.keys()]);
421
455
 
456
+ /**
457
+ * Exact utm_source normalization (lowercase key → canonical name).
458
+ *
459
+ * Use exact match when the key is short, generic, or must not accidentally
460
+ * absorb variant spellings (e.g. "impact" must not match "impact_radius").
461
+ *
462
+ * Ordering: Paid (search/social → ad networks → affiliates) →
463
+ * Organic (AI/discovery) → Retention (email → SMS → push → post-purchase)
464
+ */
465
+ const UTM_SOURCE_EXACT = {
466
+ // ── Paid – Search & Social ────────────────────────────────────────────────
467
+ google: 'Google',
468
+ adwords: 'Google',
469
+ youtube: 'Google',
470
+ yt: 'Google',
471
+ meta: 'Facebook',
472
+ facebook: 'Facebook',
473
+ instagram: 'Facebook',
474
+ ig: 'Facebook',
475
+ igshopping: 'Facebook',
476
+ threads: 'Facebook',
477
+ twitter: 'Twitter',
478
+ snapchat: 'Snapchat',
479
+ pinterest: 'Pinterest',
480
+ bing: 'Bing',
481
+ microsoft: 'Bing',
482
+ tiktok: 'TikTok',
483
+ // ── Paid – Ad Networks ───────────────────────────────────────────────────
484
+ rtbhouse: 'RTB House',
485
+ applovin: 'AppLovin',
486
+ ttd: 'The Trade Desk',
487
+ amazondsp: 'Amazon DSP',
488
+ axon: 'Axon',
489
+ duel: 'Duel',
490
+ // ── Paid – Affiliates ────────────────────────────────────────────────────
491
+ awin: 'Awin',
492
+ 'affiliate-cj': 'CJ Affiliate',
493
+ impact: 'Impact',
494
+ rakuten: 'Rakuten',
495
+ superfiliate: 'Superfiliate',
496
+ // ── Organic – AI & Discovery ─────────────────────────────────────────────
497
+ perplexity: 'Perplexity',
498
+ chatgpt: 'ChatGPT',
499
+ 'chatgpt.com': 'ChatGPT',
500
+ openai: 'ChatGPT',
501
+ 'copilot.com': 'Microsoft Copilot',
502
+ copilot: 'Microsoft Copilot',
503
+ applenews: 'Apple News',
504
+ whatsapp: 'WhatsApp',
505
+ podcast: 'Podcast',
506
+ // ── Retention – Email ────────────────────────────────────────────────────
507
+ mailchimp: 'Mailchimp',
508
+ omnisend: 'Omnisend',
509
+ iterable: 'Iterable',
510
+ listrak: 'Listrak',
511
+ sailthru: 'Sailthru',
512
+ // ── Retention – Push ─────────────────────────────────────────────────────
513
+ pushowl: 'PushOwl',
514
+ // ── Retention – Post-purchase / Payment ──────────────────────────────────
515
+ narvar: 'Narvar',
516
+ shop_app: 'Shop App',
517
+ salesforce: 'Salesforce',
518
+ yotpo: 'Yotpo',
519
+ };
520
+ /**
521
+ * Partial utm_source normalization (startsWith prefix check, lowercase).
522
+ *
523
+ * Checked after exact match so short exact keys (e.g. "ig", "yt") win first.
524
+ */
525
+ const UTM_SOURCE_PARTIAL = [
526
+ // ── Paid – Social ─────────────────────────────────────────────────────────
527
+ { prefix: 'tiktok', name: 'TikTok' },
528
+ // ── Paid – Ad Networks ───────────────────────────────────────────────────
529
+ { prefix: 'criteo', name: 'Criteo' },
530
+ // ── Retention – Email ────────────────────────────────────────────────────
531
+ { prefix: 'klaviyo', name: 'Klaviyo' },
532
+ // ── Retention – SMS ──────────────────────────────────────────────────────
533
+ { prefix: 'attentive', name: 'Attentive' },
534
+ { prefix: 'postscript', name: 'Postscript' },
535
+ // ── Retention – Post-purchase / Payment ──────────────────────────────────
536
+ { prefix: 'afterpay', name: 'Afterpay' },
537
+ { prefix: 'klarna', name: 'Klarna' },
538
+ ];
539
+ const ORGANIC_SEARCH_ENGINES = [
540
+ { match: 'google', name: 'Google' },
541
+ { match: 'bing', name: 'Bing' },
542
+ { match: 'yahoo', name: 'Yahoo' },
543
+ { match: 'duckduckgo', name: 'DuckDuckGo' },
544
+ { match: 'baidu', name: 'Baidu' },
545
+ { match: 'yandex', name: 'Yandex' },
546
+ { match: 'brave', name: 'Brave' },
547
+ ];
548
+ const KNOWN_REFERRAL_PLATFORMS = [
549
+ { match: 'facebook', name: 'Facebook' },
550
+ { match: 'instagram', name: 'Facebook' },
551
+ { match: 'twitter', name: 'Twitter' },
552
+ { match: 'x.com', name: 'Twitter' },
553
+ { match: 'tiktok', name: 'TikTok' },
554
+ { match: 'pinterest', name: 'Pinterest' },
555
+ { match: 'linkedin', name: 'LinkedIn' },
556
+ { match: 'youtube', name: 'YouTube' },
557
+ { match: 'chatgpt', name: 'ChatGPT' },
558
+ { match: 'claude', name: 'Claude' },
559
+ { match: 'perplexity', name: 'Perplexity' },
560
+ { match: 'shop.app', name: 'Shop App' },
561
+ { match: 'amazon', name: 'Amazon' },
562
+ { match: 'attentive', name: 'Attentive' },
563
+ ];
564
+ const OFFLINE_TOUCH = 'Blotout_Offline';
565
+ new Set([
566
+ ...CLICK_IDS.map((c) => c.label),
567
+ ...Object.values(UTM_SOURCE_EXACT),
568
+ ...UTM_SOURCE_PARTIAL.map((e) => e.name),
569
+ ...ORGANIC_SEARCH_ENGINES.map((e) => `Organic Search - ${e.name}`),
570
+ ...KNOWN_REFERRAL_PLATFORMS.map((e) => `Referral - ${e.name}`),
571
+ 'Referral - Other',
572
+ 'Direct Traffic',
573
+ 'Other',
574
+ OFFLINE_TOUCH,
575
+ ]);
576
+
422
577
  const getGoogleConsent = (consentData) => {
423
578
  const gadsConsent = hasUserConsentForProvider(consentData, 'googleAdsClicks');
424
579
  return {
@@ -761,7 +916,7 @@ var ProvidersGoogleAdsClicksSdk = (function () {
761
916
  var _a;
762
917
  const result = {
763
918
  isFired: false,
764
- sdkVersion: "1.53.1" ,
919
+ sdkVersion: "1.54.0" ,
765
920
  };
766
921
  if (!eventName || !window.gtag || !(manifestVariables === null || manifestVariables === void 0 ? void 0 : manifestVariables['tagId'])) {
767
922
  return result;
package/index.mjs CHANGED
@@ -42,6 +42,40 @@ const upsert = (map, key, update, createDefault) => {
42
42
  return map.set(key, update(currentValue));
43
43
  };
44
44
 
45
+ /**
46
+ * Known ad-network click ID query parameters and the human-readable provider
47
+ * label each one maps to. Used by the CDN worker to resolve `inSessionTouch`
48
+ * and by the analytics API to classify paid-media touch sessions.
49
+ *
50
+ * Keep this list in sync with `defaultParams` in queryParams.ts when new
51
+ * click ID providers are added.
52
+ */
53
+ const CLICK_IDS = [
54
+ { param: 'fbclid', label: 'Facebook' }, // Facebook Ads
55
+ { param: 'gclid', label: 'Google' }, // Google Ads (click)
56
+ { param: 'gbraid', label: 'Google' }, // Google Ads (iOS app)
57
+ { param: 'wbraid', label: 'Google' }, // Google Ads (iOS web)
58
+ { param: 'msclkid', label: 'Bing' }, // Microsoft Bing Ads
59
+ { param: 'ttclid', label: 'TikTok' }, // TikTok Ads
60
+ { param: 'ScCid', label: 'Snapchat' }, // Snapchat Ads
61
+ { param: 'epik', label: 'Pinterest' }, // Pinterest Ads
62
+ { param: 'li_fat_id', label: 'LinkedIn' }, // LinkedIn Ads
63
+ { param: 'twclid', label: 'Twitter' }, // X (Twitter) Ads
64
+ { param: 'rdt_cid', label: 'Reddit' }, // Reddit Ads
65
+ { param: 'aleid', label: 'AppLovin' }, // AppLovin
66
+ { param: 'tabclid', label: 'Taboola' }, // Taboola
67
+ { param: 'obclid', label: 'Outbrain' }, // Outbrain
68
+ { param: 'trybe', label: 'Trybe' }, // Trybe
69
+ { param: '_kx', label: 'Klaviyo' }, // Klaviyo email campaigns
70
+ { param: 'mc_eid', label: 'Mailchimp' }, // Mailchimp email campaigns
71
+ { param: 'ttd_id', label: 'The Trade Desk' }, // The Trade Desk programmatic
72
+ { param: 'evsclid', label: 'EvoSearch' }, // EvoSearch
73
+ { param: 'li_did', label: 'Live Intent' }, // LiveIntent device-level ad
74
+ { param: '_raclid', label: 'Rumble' }, // Rumble Ads
75
+ { param: 'ref_id', label: 'StackAdapt' }, // StackAdapt programmatic
76
+ { param: 'duel_a', label: 'Duel' }, // Duel referral/advocacy
77
+ ];
78
+
45
79
  const addDaysToDate = (date, days) => {
46
80
  const newDate = new Date(date);
47
81
  newDate.setDate(newDate.getDate() + days);
@@ -416,6 +450,127 @@ const usStates = new Map([
416
450
  ]);
417
451
  new Set([...isoCountries.keys(), ...usStates.keys()]);
418
452
 
453
+ /**
454
+ * Exact utm_source normalization (lowercase key → canonical name).
455
+ *
456
+ * Use exact match when the key is short, generic, or must not accidentally
457
+ * absorb variant spellings (e.g. "impact" must not match "impact_radius").
458
+ *
459
+ * Ordering: Paid (search/social → ad networks → affiliates) →
460
+ * Organic (AI/discovery) → Retention (email → SMS → push → post-purchase)
461
+ */
462
+ const UTM_SOURCE_EXACT = {
463
+ // ── Paid – Search & Social ────────────────────────────────────────────────
464
+ google: 'Google',
465
+ adwords: 'Google',
466
+ youtube: 'Google',
467
+ yt: 'Google',
468
+ meta: 'Facebook',
469
+ facebook: 'Facebook',
470
+ instagram: 'Facebook',
471
+ ig: 'Facebook',
472
+ igshopping: 'Facebook',
473
+ threads: 'Facebook',
474
+ twitter: 'Twitter',
475
+ snapchat: 'Snapchat',
476
+ pinterest: 'Pinterest',
477
+ bing: 'Bing',
478
+ microsoft: 'Bing',
479
+ tiktok: 'TikTok',
480
+ // ── Paid – Ad Networks ───────────────────────────────────────────────────
481
+ rtbhouse: 'RTB House',
482
+ applovin: 'AppLovin',
483
+ ttd: 'The Trade Desk',
484
+ amazondsp: 'Amazon DSP',
485
+ axon: 'Axon',
486
+ duel: 'Duel',
487
+ // ── Paid – Affiliates ────────────────────────────────────────────────────
488
+ awin: 'Awin',
489
+ 'affiliate-cj': 'CJ Affiliate',
490
+ impact: 'Impact',
491
+ rakuten: 'Rakuten',
492
+ superfiliate: 'Superfiliate',
493
+ // ── Organic – AI & Discovery ─────────────────────────────────────────────
494
+ perplexity: 'Perplexity',
495
+ chatgpt: 'ChatGPT',
496
+ 'chatgpt.com': 'ChatGPT',
497
+ openai: 'ChatGPT',
498
+ 'copilot.com': 'Microsoft Copilot',
499
+ copilot: 'Microsoft Copilot',
500
+ applenews: 'Apple News',
501
+ whatsapp: 'WhatsApp',
502
+ podcast: 'Podcast',
503
+ // ── Retention – Email ────────────────────────────────────────────────────
504
+ mailchimp: 'Mailchimp',
505
+ omnisend: 'Omnisend',
506
+ iterable: 'Iterable',
507
+ listrak: 'Listrak',
508
+ sailthru: 'Sailthru',
509
+ // ── Retention – Push ─────────────────────────────────────────────────────
510
+ pushowl: 'PushOwl',
511
+ // ── Retention – Post-purchase / Payment ──────────────────────────────────
512
+ narvar: 'Narvar',
513
+ shop_app: 'Shop App',
514
+ salesforce: 'Salesforce',
515
+ yotpo: 'Yotpo',
516
+ };
517
+ /**
518
+ * Partial utm_source normalization (startsWith prefix check, lowercase).
519
+ *
520
+ * Checked after exact match so short exact keys (e.g. "ig", "yt") win first.
521
+ */
522
+ const UTM_SOURCE_PARTIAL = [
523
+ // ── Paid – Social ─────────────────────────────────────────────────────────
524
+ { prefix: 'tiktok', name: 'TikTok' },
525
+ // ── Paid – Ad Networks ───────────────────────────────────────────────────
526
+ { prefix: 'criteo', name: 'Criteo' },
527
+ // ── Retention – Email ────────────────────────────────────────────────────
528
+ { prefix: 'klaviyo', name: 'Klaviyo' },
529
+ // ── Retention – SMS ──────────────────────────────────────────────────────
530
+ { prefix: 'attentive', name: 'Attentive' },
531
+ { prefix: 'postscript', name: 'Postscript' },
532
+ // ── Retention – Post-purchase / Payment ──────────────────────────────────
533
+ { prefix: 'afterpay', name: 'Afterpay' },
534
+ { prefix: 'klarna', name: 'Klarna' },
535
+ ];
536
+ const ORGANIC_SEARCH_ENGINES = [
537
+ { match: 'google', name: 'Google' },
538
+ { match: 'bing', name: 'Bing' },
539
+ { match: 'yahoo', name: 'Yahoo' },
540
+ { match: 'duckduckgo', name: 'DuckDuckGo' },
541
+ { match: 'baidu', name: 'Baidu' },
542
+ { match: 'yandex', name: 'Yandex' },
543
+ { match: 'brave', name: 'Brave' },
544
+ ];
545
+ const KNOWN_REFERRAL_PLATFORMS = [
546
+ { match: 'facebook', name: 'Facebook' },
547
+ { match: 'instagram', name: 'Facebook' },
548
+ { match: 'twitter', name: 'Twitter' },
549
+ { match: 'x.com', name: 'Twitter' },
550
+ { match: 'tiktok', name: 'TikTok' },
551
+ { match: 'pinterest', name: 'Pinterest' },
552
+ { match: 'linkedin', name: 'LinkedIn' },
553
+ { match: 'youtube', name: 'YouTube' },
554
+ { match: 'chatgpt', name: 'ChatGPT' },
555
+ { match: 'claude', name: 'Claude' },
556
+ { match: 'perplexity', name: 'Perplexity' },
557
+ { match: 'shop.app', name: 'Shop App' },
558
+ { match: 'amazon', name: 'Amazon' },
559
+ { match: 'attentive', name: 'Attentive' },
560
+ ];
561
+ const OFFLINE_TOUCH = 'Blotout_Offline';
562
+ new Set([
563
+ ...CLICK_IDS.map((c) => c.label),
564
+ ...Object.values(UTM_SOURCE_EXACT),
565
+ ...UTM_SOURCE_PARTIAL.map((e) => e.name),
566
+ ...ORGANIC_SEARCH_ENGINES.map((e) => `Organic Search - ${e.name}`),
567
+ ...KNOWN_REFERRAL_PLATFORMS.map((e) => `Referral - ${e.name}`),
568
+ 'Referral - Other',
569
+ 'Direct Traffic',
570
+ 'Other',
571
+ OFFLINE_TOUCH,
572
+ ]);
573
+
419
574
  const getGoogleConsent = (consentData) => {
420
575
  const gadsConsent = hasUserConsentForProvider(consentData, 'googleAdsClicks');
421
576
  return {
@@ -758,7 +913,7 @@ const tag = ({ data, eventName, manifestVariables, destination, pageUrl, }) => {
758
913
  var _a;
759
914
  const result = {
760
915
  isFired: false,
761
- sdkVersion: "1.53.1" ,
916
+ sdkVersion: "1.54.0" ,
762
917
  };
763
918
  if (!eventName || !window.gtag || !(manifestVariables === null || manifestVariables === void 0 ? void 0 : manifestVariables['tagId'])) {
764
919
  return result;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blotoutio/providers-google-ads-clicks-sdk",
3
- "version": "1.53.1",
3
+ "version": "1.54.0",
4
4
  "description": "Google Ads Browser SDK for EdgeTag",
5
5
  "author": "Blotout",
6
6
  "license": "MIT",