Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save siliconvallaeys/414d4ac6684097c2a67602523ba37206 to your computer and use it in GitHub Desktop.
Save siliconvallaeys/414d4ac6684097c2a67602523ba37206 to your computer and use it in GitHub Desktop.
Google Ads negative keywords may also block searches for related search terms. This script helps identify scenarios where a negative keyword typo may interfere with a positive keyword.
function main() {
// Set up the output sheet
var outputSheet = setUpOutputSheet();
// Replace with the URL of your input Google Sheet
const SPREADSHEET_URL = ''; // Add the URL of the same Google Sheet as in the first script
const sheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL).getActiveSheet();
// Fetch all keywords from active campaigns and store in a data structure
const keywordsMap = fetchAllKeywords();
// Read the spreadsheet to get the list of typos
const typoRows = sheet.getDataRange().getValues();
const header = typoRows[0];
const typoIndex = header.indexOf('typos hardcoded');
const levelIndex = header.indexOf('Level'); // Add a new column to indicate the level (Account, Campaign, Ad Group)
const campaignIndex = header.indexOf('Campaign Name'); // Campaign name column
const adGroupIndex = header.indexOf('Ad Group Name'); // Ad group name column
if (typoIndex == -1 || levelIndex == -1 || campaignIndex == -1 || adGroupIndex == -1) {
Logger.log("Required columns not found in the spreadsheet");
return;
}
// Loop through each row in the spreadsheet
for (var i = 1; i < typoRows.length; i++) {
const row = typoRows[i];
const typos = row[typoIndex].split(',');
const level = row[levelIndex];
const campaignName = row[campaignIndex];
const adGroupName = row[adGroupIndex];
// Check each typo against all keywords
typos.forEach(function(typo) {
typo = typo.trim();
if (typo) {
checkKeywordsForTypo(keywordsMap, typo, row, outputSheet, level, campaignName, adGroupName);
}
});
}
}
function fetchAllKeywords() {
const keywordsMap = {};
const campaignIterator = AdsApp.campaigns()
.withCondition("Status = ENABLED")
.get();
while (campaignIterator.hasNext()) {
const campaign = campaignIterator.next();
const campaignName = campaign.getName();
const adGroupIterator = campaign.adGroups()
.withCondition("Status = ENABLED")
.get();
while (adGroupIterator.hasNext()) {
const adGroup = adGroupIterator.next();
const adGroupName = adGroup.getName();
const keywordIterator = adGroup.keywords()
.withCondition("Status = ENABLED")
.get();
while (keywordIterator.hasNext()) {
const keyword = keywordIterator.next().getText();
keywordsMap[keyword] = {
campaign: campaignName,
adGroup: adGroupName
};
}
}
}
return keywordsMap;
}
function checkKeywordsForTypo(keywordsMap, typo, row, outputSheet, level, campaignName, adGroupName) {
for (const keyword in keywordsMap) {
const data = keywordsMap[keyword];
if (level === 'Account' ||
(level === 'Campaign' && data.campaign === campaignName) ||
(level === 'Ad Group' && data.campaign === campaignName && data.adGroup === adGroupName)) {
if (keyword.includes(typo)) {
Logger.log(`Typo found: "${typo}" in keyword "${keyword}" - Campaign: "${data.campaign}", Ad Group: "${data.adGroup}"`);
logResult(typo, keyword, data.campaign, data.adGroup, row, outputSheet);
}
}
}
}
function setUpOutputSheet() {
// Replace with the URL of your output Google Sheet
const SPREADSHEET_URL = ''; // Add the URL of the Google Sheet where you'd like to get a summary of all the negative keyword conflicts
const outputSheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL).getActiveSheet();
outputSheet.clear();
// Append the result to the spreadsheet
outputSheet.appendRow(['Possible Typo That Conflicts With Keyword', 'Keyword', 'Campaign', 'Ad Group', 'Typo Details']);
return outputSheet;
}
function logResult(typo, keyword, campaign, adGroup, row, outputSheet) {
// Append the result to the spreadsheet
outputSheet.appendRow([typo, keyword, campaign, adGroup, row.join(', ')]);
}
function main() {
// Replace with the URL of your Google Sheet
const SPREADSHEET_URL = ''; // Add the URL of the Google Sheet where all negative keywords will be listed. You will need this same URL in the next script
const sheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL).getActiveSheet();
sheet.clear(); // Clear the sheet before adding new data
// Set up headers in the Google Sheet
sheet.appendRow(['Negative Keyword', 'Level', 'Campaign Name', 'Ad Group Name']);
// Fetch campaign-level negative keywords
fetchCampaignLevelNegativeKeywords(sheet);
// Fetch ad group-level negative keywords
fetchAdGroupLevelNegativeKeywords(sheet);
// Since fetching account-level negative keywords is not directly supported,
// we need to manually add them if you have a known list or fetch through another method.
// You can add your account-level negative keywords manually here.
fetchManualAccountLevelNegativeKeywords(sheet);
}
function fetchManualAccountLevelNegativeKeywords(sheet) {
// Manually add your account-level negative keywords here
// Example: Add a list of known account-level negative keywords
const accountLevelNegatives = [
'example negative keyword 1',
'example negative keyword 2'
];
for (var i = 0; i < accountLevelNegatives.length; i++) {
sheet.appendRow([accountLevelNegatives[i], 'Account', '', '']);
}
}
function fetchCampaignLevelNegativeKeywords(sheet) {
const campaignIterator = AdsApp.campaigns().get();
while (campaignIterator.hasNext()) {
const campaign = campaignIterator.next();
const negativeKeywordIterator = campaign.negativeKeywords().get();
while (negativeKeywordIterator.hasNext()) {
const negativeKeyword = negativeKeywordIterator.next();
sheet.appendRow([negativeKeyword.getText(), 'Campaign', campaign.getName(), '']);
}
}
}
function fetchAdGroupLevelNegativeKeywords(sheet) {
const adGroupIterator = AdsApp.adGroups().get();
while (adGroupIterator.hasNext()) {
const adGroup = adGroupIterator.next();
const negativeKeywordIterator = adGroup.negativeKeywords().get();
while (negativeKeywordIterator.hasNext()) {
const negativeKeyword = negativeKeywordIterator.next();
sheet.appendRow([negativeKeyword.getText(), 'Ad Group', adGroup.getCampaign().getName(), adGroup.getName()]);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment