Google Ads does not provide an easy method for reviewing all negative keywords in an account. This can be especially frustrating when working in the Google Ads Editor tool, which only shows the negative keyword lists associated with a campaign, but not the actual negative keywords in each list.Â
This Google Ads script will create a spreadsheet with all of your negative keywords including account level, campaign level, and ad group level. As well as shared negative keyword lists.Â
If it is your first time using a Google Ads script then you may want to review this guide.
function main() {
var csvData = [];
var header = [
'Account Name', 'Account ID', 'Level', 'Level Name', 'Keyword', 'Match Type'
];
csvData.push(header);
// Get shared negative keyword lists
var negativeKeywordLists = AdsApp.negativeKeywordLists().get();
while (negativeKeywordLists.hasNext()) {
var list = negativeKeywordLists.next();
var keywords = list.negativeKeywords().get();
while (keywords.hasNext()) {
var keyword = keywords.next();
csvData.push([
AdsApp.currentAccount().getName(),
AdsApp.currentAccount().getCustomerId(),
'Shared List',
list.getName(),
keyword.getText(),
keyword.getMatchType()
]);
}
}
// Iterate through campaigns to get campaign and ad group level negative keywords
var campaignIterator = AdsApp.campaigns().withCondition('Status = ENABLED').get();
while (campaignIterator.hasNext()) {
var campaign = campaignIterator.next();
// Get campaign-level negative keywords
var campaignNegativeKeywords = campaign.negativeKeywords().get();
while (campaignNegativeKeywords.hasNext()) {
var keyword = campaignNegativeKeywords.next();
csvData.push([
AdsApp.currentAccount().getName(),
AdsApp.currentAccount().getCustomerId(),
'Campaign',
campaign.getName(),
keyword.getText(),
keyword.getMatchType()
]);
}
// Get ad group-level negative keywords
var adGroupIterator = campaign.adGroups().withCondition('Status = ENABLED').get();
while (adGroupIterator.hasNext()) {
var adGroup = adGroupIterator.next();
var adGroupNegativeKeywords = adGroup.negativeKeywords().get();
while (adGroupNegativeKeywords.hasNext()) {
var keyword = adGroupNegativeKeywords.next();
csvData.push([
AdsApp.currentAccount().getName(),
AdsApp.currentAccount().getCustomerId(),
'Ad Group',
adGroup.getName(),
keyword.getText(),
keyword.getMatchType()
]);
}
}
}
// Add a final loop for account-level negative keywords if they are not part of any list.
// This is a safety measure, as they are typically part of a hidden account-level list.
try {
var accountNegativeKeywords = AdsApp.negativeKeywordList().keywords().get();
while (accountNegativeKeywords.hasNext()) {
var keyword = accountNegativeKeywords.next();
csvData.push([
AdsApp.currentAccount().getName(),
AdsApp.currentAccount().getCustomerId(),
'Account',
'N/A',
keyword.getText(),
keyword.getMatchType()
]);
}
} catch (e) {
Logger.log("Account-level negative keywords are likely managed via a shared list. Error: " + e.message);
}
// Create and upload the CSV file to a Google Sheet
var spreadsheet = SpreadsheetApp.create('Negative Keywords Report ' + new Date().toLocaleDateString());
spreadsheet.getSheets()[0].getRange(1, 1, csvData.length, csvData[0].length).setValues(csvData);
Logger.log('Negative Keywords Report generated at: ' + spreadsheet.getUrl());
}
What’s on your mind?
"*" indicates required fields