With automatic tagging and linking of Google Ads and Analytics accounts, campaign data, keywords, and other parameters are imported into Analytics based on the gclid identifier. However, due to restrictions related to user consent for data processing, in some cases, it may not be processed.
Why does this happen? Google can identify a user based on the gclid identifier. Therefore, transmitting it to other systems and linking it with other data without the required user consent may raise privacy concerns. This is why such an identifier may sometimes not be processed by Analytics, potentially affecting a significant portion of traffic.
In this article, you will learn how to handle it.
When this occurs
Analytics can still attribute this traffic to Google Ads (google/cpc) using the mere presence of the gclid parameter in the link and other additional parameters (e.g., gad_source=1). However, the campaign attributed to such a visit might be labeled as (not set) or occasionally as (organic). Some browsers may remove the gclid parameter in enhanced privacy modes.
UTM Parameters to the Rescue
To mitigate these situations, it is recommended to add UTM parameters to Google Ads campaigns. This way, Analytics will at least capture basic data such as the campaign or keyword.
Since there are usually many ad URLs in a Google Ads account and new ad components are often created daily, this operation may seem like a significant burden.
URL Tracking Options in Google Ads
To avoid adding parameters to each link manually, Google Ads provides tracking options that automatically modify final URLs according to a specified rule, such as adding a specific string at the end of the address.
The best tracking function for adding parameters is the Final URL Suffix, which simply appends the specified parameters to the link. One of its advantages is that it doesn’t conflict with redirects to external tracking systems some advertisers use, which typically utilize a tracking template (see Google Ads Help article on tracking options).
ValueTrack Parameters
ValueTrack parameters are dynamic URL parameters used in Google Ads that automatically insert information about ad clicks into the URL, such as keywords, campaign name, or ID.
By using ValueTrack parameters in a tracking template or URL suffix, you can efficiently apply a standard pattern at the account level, ensuring that appropriate UTM parameters are added to destination URLs for each ad.
You may simply add the following Final URL Suffix in Google Ads account settings:
utm_source=google&utm_medium=cpc&utm_campaign={campaignid}&utm_id={campaignid}&utm_term={keyword}&utm_content={creative}
Note that in the above suffix, the campaign ID is passed to utm_campaign, not the name. This is because the campaign name is not an available ValueTrack parameter (see the Google ValueTrack Help article)
If you want the campaign name included, you’ll need to enter it directly in the URL:
utm_source=google&utm_medium=cpc&utm_campaign={CAMPAIGN_NAME_HERE}&utm_id={campaignid}&utm_term={keyword}&utm_content={creative}
URI Encoding
The campaign name must be in URI format, where certain characters are replaced with their symbolic representation prefixed by %, e.g., a space is represented as %20. Many tools are available online to perform this encoding (search for “URI encode tool”), and AI (like ChatGPT) can also handle this task without issue.
For example, for the campaign [SE] Search – DSA, the encoded campaign name parameter would be %5BSE%5D%20Search%20-%20DSA.
Custom Parameters
Manually pasting the campaign name into each suffix can be tedious, and errors can easily occur when handling a long suffix. A better solution is to use custom campaign parameters (also available for ad groups).
ValueTrack returns this custom parameter in the format {_parameter} (the underscore distinguishes the custom parameter and is not part of the parameter name). Thus, if a campaign parameter is added to each campaign with the campaign name encoded in URI format, a global account-level Final URL Suffix can be applied:
utm_source=google&utm_medium=cpc&utm_campaign={_campaign}&utm_id={campaignid}&utm_term={keyword}&utm_content={creative}
The custom parameter cannot exceed 250 characters.
While ValueTrack allows for transmitting other click data, only some of these can be automatically read by Analytics, which supports a limited set of allowed UTM parameters (see the Google article on UTM parameters). So, it is not illegal to use parameters like utm_adgroupid or utm_affiliateid. Still, to include this data in Analytics, these values must be passed using custom dimensions and data.
If you want to transmit ad group names, custom variables (e.g., _adgroup) should be set at the ad group level respectively.
Issues with Campaign Names
Using campaign (or ad group) names in UTM parameters poses a problem when renaming them. While changes made via the gclid identifier are reflected in Analytics for historical data, names read from UTM remain unchanged. As a result, you may see the same campaign with two different names (old and new) in data before and after the name change, complicating analysis.
Therefore, it’s better to avoid renaming campaigns, especially in Google Ads.
For sources tagged solely with UTM (without automatic Google Analytics integration), renaming will also complicate analysis. However, the impact will be limited to the period before the attribution window closes, as direct sessions and conversions are assigned to earlier visits.
Automation of Tagging
Manually tagging large ad accounts with UTM parameters is time-consuming and prone to errors. Therefore, consider solutions that at least partially automate this process.
Setting the Final URL Suffix at the account level is a one-time action and should resolve the issue. If you want a different tracking template for various campaigns, it’s still better to use one template at the account level and pass the differing parts as custom variables (e.g., the previously described _campaign variable). This will reduce data loss if tracking parameters are forgotten in new campaign settings since at least some correct parameters will be added.
Custom parameters for many Google Ads campaigns can be set in bulk. To do this, go to the Campaigns view in Google Ads Editor:
… and export the current view (Account > Export > Export Current View) to a CSV file.
In Excel, use the URL Encode function (see the Excel Help article) to encode the custom parameter value by transforming the campaign name into URI format. If your Excel lacks this function, it’s also available in Google Sheets. Then, create the Custom Parameters field value by preceding the parameter with {_campaign}=. For example, for the campaign [SE] Search – DSA, this field would be:
{_campaign}=%5BSE%5D%20Search%20-%20DSA
If the exported file already contains other custom parameters, they will appear in a single column containing both keys and values of all parameters, e.g., {_key1}=value1 {_key2}=value2
, separated by spaces. You must append the newly created parameter to existing ones using the & operator, remembering to add a space ” ” before the new parameter.
After replacing the custom parameters, copy them to the clipboard and paste them into the “Make Multiple Changes” function window, then process them.
Alternatively, save the changes to a CSV file and import it (Account > Import > From File). This is recommended for larger files where the clipboard might take up too much memory.
Automation with Google Ads Scripts
The tasks described above are suitable for automation with scripts. Below, you’ll find two useful scripts: setting the Final URL Suffix template (1a) and setting custom parameters containing the campaign name (1b).
Additionally, you’ll find an alternative solution (2), which simply sets appropriate suffixes for campaigns that already contain the campaign name.
Script 1a: Setting URL Suffixes for Campaigns
// This script sets the following URL suffix for all campaigns in the account:
// utm_source=google&utm_medium=cpc&utm_campaign={_campaign}&utm_id={campaignid}&utm_term={keyword}&utm_content={creative}
// (If you want a different suffix, modify the script below.)
// Note: For this to work, custom campaign parameters (campaign) need to be set separately using a different script or manually
// Warning: Before applying this, remove similar tracking templates if you are using them ({lpurl}?utm_source=google&utm_medium...) to avoid tag duplication.
// Check this for Account and Ad Group Settings as well!
// For account-level settings: Also set this suffix in the Google Ads panel (currently the only option).
// Scheduling: The script should be scheduled to run regularly, e.g., every hour, to add parameters to new campaigns.
// You can also manually run it after adding new campaigns.
// Warning (as of October 27, 2024): The script does not work for certain types of campaigns like Demand Gen and Video campaigns. These need to be updated manually using Google Ads Editor.
// © ADEQUATE www.adequate.digital 2024
// More info: https://adequate.digital/en/utms-for-google-ads-campaigns/
function main() {
// Process standard campaigns (Search and Display)
var campaignIterator = AdsApp.campaigns().get();
while (campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
processCampaign(campaign);
}
// Process Shopping campaigns
var shoppingCampaignIterator = AdsApp.shoppingCampaigns().get();
while (shoppingCampaignIterator.hasNext()) {
var campaign = shoppingCampaignIterator.next();
processCampaign(campaign);
}
// Process Performance Max campaigns
var pmaxCampaignIterator = AdsApp.performanceMaxCampaigns().get();
while (pmaxCampaignIterator.hasNext()) {
var campaign = pmaxCampaignIterator.next();
processCampaign(campaign);
}
// Optional: Attempt to process Demand Gen campaigns with error handling
try {
var demandGenCampaignIterator = AdsApp.demandGenCampaigns().get();
while (demandGenCampaignIterator.hasNext()) {
var campaign = demandGenCampaignIterator.next();
processCampaign(campaign);
}
} catch (e) {
Logger.log('Demand Gen campaigns may not be supported in this account: ' + e.message);
}
}
function processCampaign(campaign) {
// Set the Final URL Suffix at the campaign level
var campaignFinalUrlSuffix = "utm_source=google&utm_medium=cpc&utm_campaign={_campaign}&utm_id={campaignid}&utm_term={keyword}&utm_content={creative}";
campaign.urls().setFinalUrlSuffix(campaignFinalUrlSuffix);
Logger.log('Updated campaign "' + campaign.getName() + '" with campaign-level Final URL Suffix.');
}
1b. Script for Setting Custom Parameters for Campaigns
// This script sets the custom parameter campaign (_campaign) for all campaigns in the account. This parameter contains the campaign name transformed into a URL-compatible format and can be used in the tracking template or final URL suffix.
// Before applying: Ensure that this parameter is not used for another purpose to avoid overwriting important information. Also, check that there isn’t a campaign parameter with an empty value, as this can cause errors.
// [Schedule] The script should be scheduled to run regularly, e.g., every hour, to add parameters to new campaigns.
// It is also good to manually run it after adding new campaigns.
// [Warning] As of October 27, 2024: The script does not work for all campaign types, including Demand Gen and Video. These need to be updated manually using Google Ads Editor.
// Remember: Changing a campaign name will leave the old names in historical data in Analytics. Therefore, avoid changing campaign names.
// © ADEQUATE www.adequate.digital 2024
// More info: https://adequate.digital/en/utms-for-google-ads-campaigns/
function main() {
processAccount();
}
function processAccount() {
// Process standard campaigns (Search and Display)
var campaignIterator = AdsApp.campaigns().get();
while (campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
processCampaign(campaign);
}
// Process Shopping campaigns
var shoppingCampaignIterator = AdsApp.shoppingCampaigns().get();
while (shoppingCampaignIterator.hasNext()) {
var campaign = shoppingCampaignIterator.next();
processCampaign(campaign);
}
// Process Performance Max campaigns
var pmaxCampaignIterator = AdsApp.performanceMaxCampaigns().get();
while (pmaxCampaignIterator.hasNext()) {
var campaign = pmaxCampaignIterator.next();
processCampaign(campaign);
}
// Optional: Attempt to process Demand Gen campaigns with error handling
try {
var demandGenCampaignIterator = AdsApp.demandGenCampaigns().get();
while (demandGenCampaignIterator.hasNext()) {
var campaign = demandGenCampaignIterator.next();
processCampaign(campaign);
}
} catch (e) {
Logger.log('Demand Gen campaigns may not be supported in this account: ' + e.message);
}
}
function processCampaign(campaign) {
var campaignName = campaign.getName();
// Percent-encode the campaign name
var modifiedCampaignName = encodeURIComponent(campaignName);
// Truncate to 250 characters
if (modifiedCampaignName.length > 250) {
Logger.log('Warning: The encoded campaign name for "' + campaignName + '" exceeds 250 characters and will be truncated.');
modifiedCampaignName = modifiedCampaignName.substring(0, 250);
}
// Get existing custom parameters at the campaign level
var customParameters = campaign.urls().getCustomParameters() || {};
// Update or add the 'campaign' parameter
customParameters['campaign'] = modifiedCampaignName;
// Set the updated custom parameters back to the campaign
campaign.urls().setCustomParameters(customParameters);
Logger.log('Updated campaign "' + campaignName + '" with campaign=' + modifiedCampaignName);
}
2. Alternative solution
Alternatively, you can simply set a tracking template containing the encoded campaign name for all campaigns. This script will be more resistant to errors, but setting missing parameters through Google Ads Editor will be more challenging.
// This script sets a tracking template for each campaign as follows:
// utm_source=google&utm_medium=cpc&utm_campaign={CAMPAIGN_NAME_HERE}&utm_id={campaignid}&utm_term={keyword}&utm_content={creative}
// Warning (as of October 27, 2024): The script does not work for certain types of campaigns like Demand Gen and Video campaigns. These need to be updated manually using Google Ads Editor
// © ADEQUATE www.adequate.digital 2024
// More info: https://adequate.digital/en/utms-for-google-ads-campaigns/
function main() {
// Helper function to update campaigns
function updateCampaignUrls(campaignIterator) {
while (campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
// Get the campaign name and URI encode it
var campaignName = encodeURIComponent(campaign.getName());
// Construct the final URL suffix with UTM parameters
var finalUrlSuffix = 'utm_source=google&utm_medium=cpc&utm_campaign=' + campaignName +
'&utm_id={campaignid}&utm_term={keyword}&utm_content={creative}';
// Set the final URL suffix for the campaign
campaign.urls().setFinalUrlSuffix(finalUrlSuffix);
// Log the changes for verification
Logger.log('Updated Final URL Suffix for Campaign: ' + campaign.getName());
Logger.log('New Final URL Suffix: ' + finalUrlSuffix);
}
}
// Update Search and Display campaigns by filtering
var searchAndDisplayCampaigns = AdsApp.campaigns()
.withCondition("AdvertisingChannelType IN ['SEARCH', 'DISPLAY']")
.get();
updateCampaignUrls(searchAndDisplayCampaigns);
// Update Performance Max campaigns
var performanceMaxCampaigns = AdsApp.performanceMaxCampaigns().get();
updateCampaignUrls(performanceMaxCampaigns);
// Update Shopping campaigns
var shoppingCampaigns = AdsApp.shoppingCampaigns().get();
updateCampaignUrls(shoppingCampaigns);
}
Due to evolving technologies, the described features and scripts may become outdated. Please let us know if you notice that the article needs an update or if you find any errors.