Last active
May 6, 2025 20:58
-
-
Save caseypage/5fc3b5bd4ae2fbcdff1286c7bce94a05 to your computer and use it in GitHub Desktop.
This will automate setting custom parameters for your adwords tracking template at the campaign and adgroup level.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Sample Tracking Template | |
// {lpurl}?utm_medium=adwords&utm_campaign={_campaign}&utm_source={_adgroup}&utm_term={keyword} | |
// This script will set custom parameters {_campaign} and {_adgroup} at the campaign and adgroup level respectively. | |
// Configuration | |
// Set the Parameter Format Mode to either "safe" or "strict" | |
const PARAMETER_FORMAT_MODE = 'safe'; | |
function main() { | |
updateCampaigns(); | |
updateAdGroups(); | |
} | |
function formatParameterValue(name, mode = 'safe') { | |
// adjust accordingly below | |
if (mode === 'strict') { | |
return name | |
.replace(/[^a-zA-Z0-9 ]+/g, '') // remove non-alphanumerics | |
.toLowerCase() // make lower case | |
.trim() // remove beginning or trailing spaces | |
.replace(/[^\w\-\.~ ]+/g, '') // remove anything not URL-safe | |
.replace(/\s+/g, '_') // replace spaces with underscores | |
.substr(0, 100); // limit to 100 characters | |
} else { | |
return name | |
.trim() // remove beginning or trailing spaces | |
.replace(/[^\w\-\.~ ]+/g, '') // remove anything not URL-safe | |
.replace(/\s+/g, '_') // replace spaces with underscores | |
.substr(0, 100); // limit to 100 characters | |
} | |
} | |
function getNewCustomParameters(adwordsObject, parameterName, parameterValue) { | |
let customParameters = adwordsObject.urls().getCustomParameters(); | |
let newCustomParameters = {}; | |
if (customParameters == null) { | |
newCustomParameters[parameterName] = parameterValue; | |
} else { | |
if (customParameters.hasOwnProperty(parameterName)) { | |
customParameters[parameterName] = parameterValue; | |
} else if (Object.keys(customParameters).length < 3) { | |
customParameters[parameterName] = parameterValue; | |
} | |
newCustomParameters = customParameters; | |
} | |
return newCustomParameters; | |
} | |
function updateCampaigns() { | |
const query = ` | |
SELECT | |
campaign.id, | |
campaign.name, | |
campaign.status | |
FROM campaign | |
WHERE | |
campaign.status IN ('ENABLED', 'PAUSED') | |
`; | |
const iterator = AdsApp.search(query); | |
while (iterator.hasNext()) { | |
const row = iterator.next(); | |
Logger.log(JSON.stringify(row)); | |
const campaign = row.campaign; | |
const campaignName = campaign.name; | |
const paramValue = formatParameterValue(campaignName, PARAMETER_FORMAT_MODE); | |
try { | |
const campaignIterator = AdsApp.campaigns() | |
.withIds([campaign.id]) | |
.get(); | |
if (campaignIterator.hasNext()) { | |
const campaignEntity = campaignIterator.next(); | |
const newCustomParameters = getNewCustomParameters(campaignEntity, 'campaign', paramValue); | |
Logger.log(`Campaign: ${campaignName} | ${paramValue}`); | |
campaignEntity.urls().setCustomParameters(newCustomParameters); | |
} else { | |
Logger.log(`Campaign ID ${campaign.id} not found (possibly deleted)`); | |
} | |
} catch (error) { | |
Logger.log(`Error updating Campaign ID ${campaign.id}: ${error.message}`); | |
} | |
} | |
} | |
function updateAdGroups() { | |
const query = ` | |
SELECT | |
ad_group.id, | |
ad_group.name, | |
ad_group.status, | |
ad_group.campaign | |
FROM ad_group | |
WHERE | |
ad_group.status IN ('ENABLED', 'PAUSED') AND | |
campaign.status IN ('ENABLED', 'PAUSED') | |
`; | |
const iterator = AdsApp.search(query); | |
while (iterator.hasNext()) { | |
const row = iterator.next(); | |
const adGroup = row.adGroup; | |
const adGroupName = adGroup.name; | |
const paramValue = formatParameterValue(adGroupName, PARAMETER_FORMAT_MODE); | |
try { | |
const adGroupIterator = AdsApp.adGroups() | |
.withIds([adGroup.id]) | |
.get(); | |
if (adGroupIterator.hasNext()) { | |
const adGroupEntity = adGroupIterator.next(); | |
const newCustomParameters = getNewCustomParameters(adGroupEntity, 'adgroup', paramValue); | |
Logger.log(`AdGroup: ${adGroupName} | ${paramValue}`); | |
adGroupEntity.urls().setCustomParameters(newCustomParameters); | |
} else { | |
Logger.log(`AdGroup ID ${adGroup.id} not found (likely orphaned)`); | |
} | |
} catch (error) { | |
Logger.log(`Error updating AdGroup ID ${adGroup.id}: ${error.message}`); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Just got around to looking at this. For updating custom parameters on a campaign, you use CampaignUrls to do that. The issue is that Demand Gen and Video campaigns do not support this.
The previous version of my script used a method that did not return Demand Gen or Video campaigns.. so I updated the script to use GAQL (Google Ads Query Language) .. this does in fact return the campaigns now, but they do not support the CampaignUrls() method I need to update the parameters. Maybe at some point in the future they'll add support for Demand Gen & Video campaigns via an AdWords App script.