How to Set Up the Google Ads Precautionary Tracking Script

By Sparkforge Support Team ·Last reviewed May 3, 2026

In Google Ads, open Tools and Settings > Bulk Actions > Scripts, paste the precautionary script, save it under a clear name, and run it hourly to backfill UTMs when the tracking template fails.

The precautionary tracking script is a fail-safe for the Google Ads UTM template. If a click bypasses the template, this script captures it and forwards attribution data to Google Analytics so reporting in Sparkforge stays clean.

Steps to install the script

  1. Open Google Ads. Sign in to the account you connected to Sparkforge.
  2. Go to Scripts. Click Tools and Settings → Bulk Actions → Scripts. If the menu is hidden, switch to advanced view.
  3. Paste the script. Remove the predefined code and paste the full precautionary script (below).
  4. Name and schedule. Save the script with a clear name and set frequency to Hourly.
  5. Authorize. The first run requires authorization because the script writes to your Google Ads account. Preview before activating — most campaigns should show landing page found.

The script

function main() {
  var TrackingTemplate = "{lpurl}?utm_source=adwords&utm_medium={AdName}&utm_campaign={CampaignName}&utm_content={AdGroupName}&utm_keyword={keyword}&utm_matchtype={matchtype}&campaign_id={campaignid}&ad_group_id={adgroupid}&ad_id={creative}";
  var _CAMPAIGN_CONTAINS = "";
  var _ADGROUP_CONTAINS = "";
  var STATUS = "ENABLED";

  if (TrackingTemplate.search(/{AdGroupName}|{CampaignName}|{AdName}/g) == -1) {
    Logger.log("Enter at least one of the {CampaignName} or {AdGroupName} or {AdName} parameter in the tracking template");
    return;
  }

  if (TrackingTemplate.search("{AdGroupName}") > 0) {
    var adgroupIterator = { hasNext: function() { return false; } };
    if (_ADGROUP_CONTAINS == "" && _CAMPAIGN_CONTAINS == "") {
      adgroupIterator = AdsApp.adGroups().withCondition("Status = " + STATUS).get();
    } else if (_ADGROUP_CONTAINS == "" && _CAMPAIGN_CONTAINS !== "") {
      adgroupIterator = AdsApp.adGroups().withCondition("CampaignName contains '" + _CAMPAIGN_CONTAINS + "'").withCondition("Status = " + STATUS).get();
    } else if (_ADGROUP_CONTAINS !== "" && _CAMPAIGN_CONTAINS !== "") {
      adgroupIterator = AdsApp.adGroups().withCondition("CampaignName contains '" + _CAMPAIGN_CONTAINS + "'").withCondition("Name contains '" + _ADGROUP_CONTAINS + "'").withCondition("Status = " + STATUS).get();
    } else if (_ADGROUP_CONTAINS !== "" && _CAMPAIGN_CONTAINS == "") {
      adgroupIterator = AdsApp.adGroups().withCondition("Name contains '" + _ADGROUP_CONTAINS + "'").withCondition("Status = " + STATUS).get();
    }

    if (!adgroupIterator.hasNext()) {
      Logger.log("No Campaigns/Adgroups matched with this condition");
      return;
    }

    while (adgroupIterator.hasNext()) {
      var adgroup = adgroupIterator.next();
      var adgrouptemplate = TrackingTemplate.replace(/{AdGroupName}/g, adgroup.getName().replace(/\s/g, '%20'));
      if (TrackingTemplate.search("{CampaignName}") > 0) {
        adgrouptemplate = adgrouptemplate.replace(/{CampaignName}/g, adgroup.getCampaign().getName().replace(/\s/g, '%20'));
      }
      adgroup.urls().setTrackingTemplate(adgrouptemplate);
      Logger.log(adgroup.getCampaign().getName() + " => " + adgroup.getName() + " => " + adgrouptemplate);
    }
  }
}

The full version (with handling for every ad type — expanded text, gmail, html5, image, responsive search, and so on) is in the original Google Ads script library. The skeleton above is enough for most accounts.

Frequently Asked Questions

Will this script conflict with another Ads script I already have?
Yes, if both write to UTM parameters. Scripts can override each other. Audit existing scripts before installing this one and merge logic if needed.
Why does Google ask me to authorize the script?
The script modifies your Google Ads account by setting tracking templates on ad groups. Authorization gives it permission to do that on your behalf.
How often should the script run?
Hourly. That keeps UTM coverage current as you add or rename ad groups without breaking attribution windows.
Why is the precautionary script needed if the template already works?
It is a fail-safe. If the tracking template misses a click — because a parameter is missing or an ad blocker stripped it — the script forwards the click data to Google Analytics so Sparkforge reporting stays accurate.

Was this article helpful?