free · open source · no signup

Is Your Ad Tracking
Actually Working?

Simulate an ad click or paste your URL with tracking params. Instantly check GCLID capture, UTM persistence, localStorage state, and form field population — then grab a ready-to-deploy script for your platform.

URL
LIVE TRACKING STATUS
URL Parameters scanning…
🔗
No tracking params in URL.
Hit “Simulate Google Ad Click” to test.
localStorage State scanning…
💾
No tracking data stored.
Simulate an ad click to test cross-page persistence.
Platform Detection scanning…
Form Field Scanner scanning…
📋
No tracking fields on this page.
Load this tool on your actual landing/form page for a live scan.
Platform Scripts GTM → Custom HTML → All Page Views
Marketo / Web-to-Lead: Standard Google script uses getElementById() — silently fails on Marketo (no id attribute on hidden fields). This version uses querySelector('[name=…]') and is confirmed working.
scripts/salesforce.js
// Salesforce GCLID Capture — querySelector version (Marketo compatible)
// GTM: Tags → Custom HTML → Trigger: All Page Views
// STEP 1: Find field names: DevTools console on your form page:
//   Array.from(document.querySelectorAll('input[type=hidden]'))
//     .forEach(i => console.log('name:', i.name, '| id:', i.id))
// STEP 2: Update GCLID_FIELDS below

(function() {
  var GCLID_FIELDS = [
    'Gclid__c',    // primary field — UPDATE this
    'btURLGclid',  // secondary — remove if not needed
  ];
  var EXPIRY = 90 * 24 * 60 * 60 * 1000;

  function run() {
    var gclid = (RegExp('[?&]gclid=([^&]*)').exec(location.search)||[])[1];
    var src   = (RegExp('[?&]gclsrc=([^&]*)').exec(location.search)||[])[1];
    gclid = gclid && decodeURIComponent(gclid.replace(/\+/g,' '));

    if (gclid && (!src || src.indexOf('aw') !== -1)) {
      try { localStorage.setItem('gclid', JSON.stringify({value:gclid, expiryDate:Date.now()+EXPIRY})); } catch(e){}
    }

    var rec = null;
    try { rec = JSON.parse(localStorage.getItem('gclid')); } catch(e){}
    if (!rec || Date.now() > rec.expiryDate) return;

    GCLID_FIELDS.forEach(function(name) {
      var el = document.querySelector('[name="'+name+'"]');
      if (el) el.value = rec.value;
    });
  }
  window.addEventListener('load', run);
})();
SALESFORCE SETUP — 5 STEPS
1
Create GCLID field on Lead
Object Manager → Lead → Fields → New → Text, 255 chars, name: GCLID (API: GCLID__c)
2
Create GCLID field on Opportunity
Same on Opportunity object
3
Map Lead → Opportunity (critical)
Setup → Lead Field Mapping → map GCLID__c on Lead → GCLID__c on Opportunity
4
Enable Field History Tracking
Track Lead Status + Opportunity Stage — Data Manager detects conversions from these history changes
5
Link in Google Ads Data Manager
Tools → Data Manager → Salesforce → Direct Linking. Two connections: one for Lead, one for Opportunity. Production org only.
💡 HubSpot has a native Google Ads integration (Settings → Integrations → Google Ads). Enable that for primary conversion sync. Use this script as a localStorage fallback for multi-page journeys.
scripts/hubspot.js
// HubSpot GCLID + UTM — multi-page journey support
// GTM: Tags → Custom HTML → Trigger: All Page Views
// UPDATE: FIELD_MAP values = HubSpot contact property internal names

(function() {
  var EXP = 90 * 24 * 60 * 60 * 1000;
  var FIELD_MAP = {
    'gclid':        'gclid__c',
    'utm_source':   'utm_source__c',
    'utm_medium':   'utm_medium__c',
    'utm_campaign': 'utm_campaign__c',
    'utm_content':  'utm_content__c',
  };
  function sv(k,v){ if(v) try{localStorage.setItem('hs_'+k,JSON.stringify({v,exp:Date.now()+EXP}));}catch(e){} }
  function lv(k){ try{var d=JSON.parse(localStorage.getItem('hs_'+k)); return d&&Date.now()<d.exp?d.v:null;}catch(e){return null;} }
  function cap(){ Object.keys(FIELD_MAP).forEach(function(p){ var m=RegExp('[?&]'+p+'=([^&]*)').exec(location.search); if(m) sv(p,decodeURIComponent(m[1].replace(/\+/g,' '))); }); }
  function fill(){ Object.keys(FIELD_MAP).forEach(function(p){ var v=lv(p), el=document.querySelector('[name="'+FIELD_MAP[p]+'"]')||document.querySelector('[name="'+p+'"]'); if(el&&v)el.value=v; }); }
  window.addEventListener('message',function(e){if(e.data&&e.data.type==='hsFormCallback'&&e.data.eventName==='onFormReady')setTimeout(fill,100);});
  window.addEventListener('load',function(){ cap(); fill(); });
})();
HUBSPOT SETUP
1
Create gclid__c contact property
Settings → Properties → Contact → Create → Single-line text, Internal name: gclid__c
2
Add hidden field to forms
Form editor → Add field → Hidden → select GCLID property → Pre-populate from URL param: gclid
3
Enable native Google Ads integration
Settings → Integrations → Google Ads → Connect → map submissions to conversion actions
4
Deploy this script via GTM
Handles multi-page journeys where user doesn't land directly on the form page
scripts/wordpress.js — Gravity Forms · CF7 · WPForms · Elementor · Ninja Forms
// WordPress GCLID + UTM — all major form plugins
// Includes plugin hooks + MutationObserver for AJAX/modal forms
// GTM: Tags → Custom HTML → Trigger: All Page Views

(function() {
  var EXP=90*24*60*60*1000, NS='wp_';
  function sv(k,v){if(v)localStorage.setItem(NS+k,JSON.stringify({v,exp:Date.now()+EXP}));}
  function gv(k){try{var d=JSON.parse(localStorage.getItem(NS+k));return d&&Date.now()<d.exp?d.v:null;}catch(e){return null;}}
  function fi(s,v){if(v)document.querySelectorAll(s).forEach(function(e){e.value=v;});}
  function cap(){
    ['gclid','utm_source','utm_medium','utm_campaign','utm_content','utm_term']
      .forEach(function(p){var m=RegExp('[?&]'+p+'=([^&]*)').exec(location.search);if(m)sv(p,decodeURIComponent(m[1].replace(/\+/g,' ')));});
  }
  function fill(){
    fi('[name*="gclid"],[name*="GCLID"],[id*="gclid"],[name="google_click_id"]',gv('gclid'));
    fi('[name*="utm_source"],[name*="UTM_Source"]',gv('utm_source'));
    fi('[name*="utm_medium"],[name*="UTM_Medium"]',gv('utm_medium'));
    fi('[name*="utm_campaign"],[name*="UTM_Campaign"]',gv('utm_campaign'));
  }
  document.addEventListener('gform_post_render',fill);    // Gravity Forms
  document.addEventListener('wpcf7mailsent',fill);          // CF7
  document.addEventListener('wpformsAjaxSubmitSuccess',fill); // WPForms
  document.addEventListener('elementor/popup/show',fill);    // Elementor
  if(window.MutationObserver){var t; new MutationObserver(function(ms){
    if(ms.some(function(m){return Array.from(m.addedNodes).some(function(n){return n.querySelector&&n.querySelector('input');});}))
      {clearTimeout(t);t=setTimeout(fill,150);}
  }).observe(document.body,{childList:true,subtree:true});}
  window.addEventListener('load',function(){cap();fill();});
})();
Checkout domain boundary: Shopify checkout is on checkout.shopify.com. localStorage cannot cross domains. This script appends tracking to checkout links as a URL workaround. For purchase conversions use the Google & YouTube channel app from the Shopify App Store.
scripts/shopify.js — theme.liquid or GTM
// Shopify GCLID + UTM
// Deploy: GTM or paste before </body> in theme.liquid
// Appends tracking params to checkout/cart links

(function(){
  var EXP=90*24*60*60*1000,NS='shp_',P=['gclid','utm_source','utm_medium','utm_campaign'];
  function sv(k,v){try{localStorage.setItem(NS+k,JSON.stringify({v,exp:Date.now()+EXP}));}catch(e){}}
  function gv(k){try{var d=JSON.parse(localStorage.getItem(NS+k));return d&&Date.now()<d.exp?d.v:null;}catch(e){return null;}}
  function cap(){P.forEach(function(p){var m=RegExp('[?&]'+p+'=([^&]*)').exec(location.search);if(m)sv(p,decodeURIComponent(m[1]));});}
  function app(){
    var parts=[];P.forEach(function(p){var v=gv(p);if(v)parts.push(p+'='+encodeURIComponent(v));});
    if(!parts.length)return;
    var qs=parts.join('&');
    document.querySelectorAll('a[href*="/checkout"],a[href*="/cart"]').forEach(function(a){
      if(a.href&&!a.href.includes('gclid')) a.href+=(a.href.includes('?')?'&':'?')+qs;
    });
  }
  if(window.MutationObserver)new MutationObserver(app).observe(document.body,{childList:true,subtree:true});
  window.addEventListener('load',function(){cap();app();});
})();
💡 For purchase conversions: install Google & YouTube channel app from Shopify App Store. It handles checkout-domain tracking natively.
💡 Platform-agnostic. Captures gclid, msclkid, fbclid, li_fat_id + all UTMs. Fills any hidden input matching common tracking name patterns. Exposes window.AdTrackDiag.dump() for console debugging.
scripts/universal.js
// Universal Ad Tracking — any platform, any form
// GTM: Tags → Custom HTML → Trigger: All Page Views

(function(){
  var EXP=90*24*60*60*1000,NS='_adt_';
  function gp(p){var m=RegExp('[?&]'+p+'=([^&]*)').exec(location.search);return m?decodeURIComponent(m[1].replace(/\+/g,' ')):null;}
  function sv(k,v){if(v)try{localStorage.setItem(NS+k,JSON.stringify({v,exp:Date.now()+EXP}));}catch(e){}}
  function lv(k){try{var d=JSON.parse(localStorage.getItem(NS+k));return d&&Date.now()<d.exp?d.v:null;}catch(e){return null;}}
  function fi(s,v){if(!v)return;document.querySelectorAll(s).forEach(function(e){e.value=v;});}

  function run(){
    ['gclid','msclkid','fbclid','li_fat_id','utm_source','utm_medium','utm_campaign','utm_content','utm_term']
      .forEach(function(p){sv(p,gp(p));});
    fi('[name*="gclid"],[name*="GCLID"],[name*="Gclid"],[id*="gclid"],[name="Gclid__c"],[name="gclid__c"],[name="btURLGclid"],[name="google_click_id"]',lv('gclid'));
    fi('[name*="msclkid"],[id*="msclkid"]',lv('msclkid'));
    ['utm_source','utm_medium','utm_campaign','utm_content','utm_term'].forEach(function(p){fi('[name*="'+p+'"]',lv(p));});
  }
  if(window.MutationObserver){var t;new MutationObserver(function(ms){
    if(ms.some(function(m){return Array.from(m.addedNodes).some(function(n){return n.querySelector&&n.querySelector('input');});}))
      {clearTimeout(t);t=setTimeout(run,150);}
  }).observe(document.body,{childList:true,subtree:true});}
  window.addEventListener('load',run);

  window.AdTrackDiag={
    dump:function(){['gclid','msclkid','utm_source','utm_medium','utm_campaign'].forEach(function(k){console.log((lv(k)?'✓':'○'),k+':',lv(k)||'not stored');});},
    simulate:function(g){var f=g||'TEST_'+Math.random().toString(36).substr(2,9).toUpperCase();sv('gclid',f);sv('utm_source','google');sv('utm_medium','cpc');run();console.log('Simulated:',f);}
  };
})();
💡 Paste in DevTools console (F12) on any page of your site.
Check all tracking values
['gclid','utm_source','utm_medium','utm_campaign','utm_content','utm_term'].forEach(p => {
  const url = new URLSearchParams(location.search).get(p);
  const ls  = ['','_adt_','hs_','wp_','shp_'].reduce((a,ns) => {
    if (a) return a;
    try { const d=JSON.parse(localStorage.getItem(ns+p)); return d?.v||d?.value||null; } catch(e){return null;}
  }, null);
  console.log((url||ls?'✓':'✗'), p+':', url?`URL:${url}`:ls?`LS:${ls}`:'NOT FOUND');
});
List all hidden form fields
Array.from(document.querySelectorAll('input[type=hidden]'))
  .map(i=>({name:i.name||'(none)',id:i.id||'(none)',value:i.value||'(empty)'}))
  .forEach((i,n)=>console.log('['+n+']',JSON.stringify(i)));
Inject fake GCLID into all localStorage namespaces
const fake='TEST_'+Math.random().toString(36).substr(2,9).toUpperCase();
const exp=Date.now()+90*24*60*60*1000;
['','_adt_','hs_','wp_','shp_'].forEach(ns=>
  localStorage.setItem(ns+'gclid',JSON.stringify(ns===''?{value:fake,expiryDate:exp}:{v:fake,exp}))
);
console.log('✓ Stored:', fake);
Clear all tracking data
const r=Object.keys(localStorage).filter(k=>/gclid|utm_|_adt_|hs_|wp_|shp_|msclkid|fbclid/i.test(k));
r.forEach(k=>localStorage.removeItem(k));
console.log('Cleared',r.length,'keys:',r);
👉 Drag the button below to your bookmarks bar. Then go to any client's form page, click it, and get a floating panel showing every hidden field, the detected platform, and a pre-configured script with the real field names already filled in.
📊 Ad Track Diagnostic
↑ drag this to your bookmarks bar
WHAT IT DOES ON ANY PAGE
1Scans every hidden <input> on the page β€” shows name, id, and current value
2Detects platform: Marketo, HubSpot, Gravity Forms, WPForms, CF7, Elementor, Shopify, GTM, GA4
3Checks localStorage for stored GCLIDs across all platform namespaces
4Generates a pre-configured script with the actual field names found on that page already substituted in
5One-click copy β€” paste straight into GTM
⚠ If your browser blocks the drag, right-click the button β†’ Bookmark this link instead. Chrome and Edge work best; Firefox may require right-click.
KEY LIMITS — KNOW BEFORE YOU LAUNCH
90 days
Hard cutoff
Conversions >90 days after ad click are permanently rejected
4–6 hrs
First import
Wait after creating a conversion action before first import runs
14 days
Initial lookback
First-ever import only goes back 14 days — have leads ready first
No retry
Failed imports
Failed imports don’t auto-retry — manually trigger in Data Manager
1 object
Per connection
Need two Data Manager connections: one for Lead, one for Opportunity
Prod only
Salesforce env
Sandbox not supported — production org only