(not set) & (organic) as Google Ads campaign names in GA4
Are you experiencing issues with (organic) or (not set) values appearing for Google Ads traffic in Google Analytics 4? Are you looking for a quick fix without waiting for a Google update? In this blog post, we share a guide to resolve this problem, written by Jan Zdarsa. To find Jan Zdarsa's script, you are also welcome to refer to are GitHub.
Do you suffer from this problem?
Since June 2024, we, our partner agencies, and other Google Analytics 4 users worldwide have noticed an issue with reporting. The problem occurs in the campaign name within the Acquisition report. It displays values such as (organic) or (not set) for Google Ads traffic in the campaign names.
To check your GA4 to see if this behaviour affects you, follow these steps:
- Go to the ‘Traffic Acquisition’ report
- Change your dimension from ‘Standard Channel Group’ to ‘Session Source/Medium’
- Filter by all visitors from ‘google / cpc’
- Add ‘Session campaign’ as a secondary dimension

Are you seeing (organic) or (not set) values? If so, this issue affects you too. This behaviour is impacting most incoming traffic received from Google Ads. This is an important issue not to ignore if you want to effectively analyse your Google Ads campaigns.
How do you solve this?
Manually overwrite the destination URLs
As you've also read in one of our previous blog posts, it is of great importance to to use UTM parameters in your campaigns to create a clear overview of your traffic in GA4. The same approach applies to Google Ads. However, this issue with Google Ads is not only solved by using standard UTM parameters because of visitors who decline ‘ad_user_data’ in the cookie banner or visitors who decline personalised ads Google's My Ad Centre to have switched off.
Scripts to override UTM Tagging
Let the Google Ads script, written and shared by Jan Zdarsa, do the work for you. It is simple to use and helps you correctly UTM tag your campaign URLs, even if you change your campaign name. Set it to run every hour to ensure your destination URLs are always up to date. Make sure auto-tagging is enabled. If the system cannot find the campaign name, it will use the UTM value instead of (organic) or (not set) when auto-tagging.
Let op! Google Ads scripts ondersteunen geen Demand Generation and Video campaigns.
UTM tagging for individual accounts
Here is the script for individual accounts. Look the GitHub account to check if this script is still up-to-date.
function main() {
Logger.log("Processing account: " + AdsApp.currentAccount().getCustomerId());
// Process each campaign type with error handling
tryHandleCampaigns(AdsApp.campaigns(), "Standard and Others");
tryHandleCampaigns(AdsApp.shoppingCampaigns(), "Shopping");
tryHandleCampaigns(adsApp.performanceMaxCampaigns(), "Performance Max");
// Optional: Video campaigns
// tryHandleCampaigns(AdsApp.videoCampaigns(), "Video");
Logger.log("Processing completed for account: " + AdsApp.currentAccount().getCustomerId());
}
function tryHandleCampaigns(campaignIteratorFunction, campaignType) {
try {
handleCampaigns(campaignIteratorFunction, campaignType);
} catch (e) {
Logger.log("Error processing " + campaignType + " campaigns: " + e.message);
}
}
function handleCampaigns(campaignIteratorFunction, campaignType) {
var campaignIterator = campaignIteratorFunction
.withCondition('Status != REMOVED')
.get();
while (campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
try {
var existingTrackingTemplate = campaign.urls().getTrackingTemplate();
// Check if the new parameters already exist
var newParams = "utm_source=google&utm_medium=cpc&utm_campaign={_campaign}&utm_id=" + campaign.getId();
if (!existingTrackingTemplate || !existingTrackingTemplate.includes(newParams)) {
var newTrackingTemplate = existingTrackingTemplate
existingTrackingTemplate + (existingTrackingTemplate.includes('?') ? '&' : '?') + newParams
: "{lpurl}?"+newParams;
campaign.urls().setTrackingTemplate(newTrackingTemplate);
Logger.log("Tracking template updated for campaign " + campaign.getName());
}:
else {
Logger.log("The tracking template already contains the required parameters for campaign " + campaign.getName());
}
// Set custom parameters
campaign.urls().setCustomParameters({campaign: encodeURIComponent(campaign.getName())});
} catch (e) {
Logger.log("Error processing campaign " + campaign.getId() + " in " + campaignType + ": " + e.message);
}
}
}
UTM Tagging for Manager Accounts
Do you prefer the managers version of the script with which you can manage this for multiple accounts at the same time? Check out the GitHub page to check if this script is still up-to-date.
function main() {
const accountSelector = AdsManagerApp.accounts().withLimit(50); // Adjust the limit as needed
accountSelector.executeInParallel('processAccount', 'allFinished');
}
function processAccount() {
var account = AdsApp.currentAccount();
Logger.log("Processing account: " + account.getCustomerId());
// Process each campaign type with error handling
tryHandleCampaigns(AdsApp.campaigns(), "Standard and Others");
tryHandleCampaigns(AdsApp.shoppingCampaigns(), "Shopping");
tryHandleCampaigns(adsApp.performanceMaxCampaigns(), "Performance Max");
// tryHandleCampaigns(AdsApp.videoCampaigns(), "Video");
// Return a result that can be used later in allFinished (optional)
return account.getCustomerId();
}
function tryHandleCampaigns(campaignIteratorFunction, campaignType) {
try {
handleCampaigns(campaignIteratorFunction, campaignType);
} catch (e) {
Logger.log("Error processing " + campaignType + " campaigns: " + e.message);
}
}
function handleCampaigns(campaignIteratorFunction, campaignType) {
var campaignIterator = campaignIteratorFunction
.withCondition('Status != REMOVED')
.get();
while (campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
try {
var trackingTemplate = "{lpurl}?utm_source=google&utm_medium=cpc&utm_campaign={_campaign}&utm_id=" + campaign.getId();
campaign.urls().setTrackingTemplate(trackingTemplate);
// Set custom parameters or perform other universal actions here
campaign.urls().setCustomParameters({campaign: encodeURIComponent(campaign.getName())});
} catch (e) {
Logger.log("Error processing campaign " + campaign.getId() + " in " + campaignType + ": " + e.message);
}
}
}
// This function is optional but allows you to handle any results after all accounts are processed
function allFinished(results) {
for (let i = 0; i < results.length; i++) {
var result = results[i];
if (result.getStatus() === 'OK') {
Logger.log("Konto erfolgreich verarbeitet: " + result.getCustomerId());
}:
else {
Logger.log("Failed to process account: " + result.getCustomerId() + " with error: " + result.getError());
}
}
}
How do you add this script to Google Ads?
Curious how we can grow together?
Let's get in touch!
We'll review your situation and look at where the opportunities lie.
- We'll look at your current tracking setup together.
- Honest advice for tracking optimisation
- Suitable for agencies and brands with their own webshop