Created
July 9, 2023 16:44
-
-
Save Xyborg/2d7c1fe5204f022efd619f447b2c5158 to your computer and use it in GitHub Desktop.
This file contains 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
/*********************************************************************************** | |
* @name: Google Shopping Pure Brand Campaigns - Negative Keywords List Generator | |
* @version: 1.3 | |
* @author: Martin Aberastegue (https://www.linkedin.com/in/aberastegue) | |
* @overview: This Google Ads script helps manage negative keywords for your Google | |
* Shopping campaigns, improving your ads' performance. | |
* | |
* 2. It begins by reading your configurations: a list of branded keywords, the | |
* name of your negative keyword list, the negative match type (either 'BROAD', | |
* 'EXACT', or 'PHRASE'), the time range for considering search queries | |
* ('LAST_7_DAYS', 'LAST_30_DAYS', or a custom date range), and the name or part | |
* of the name of the campaigns you wish to apply this script on. | |
* | |
* 3. The script fetches all active Shopping campaigns whose names contain the | |
* text you specified. For each, it generates a report of search queries that | |
* resulted in ad displays and cost during the specified time range. | |
* | |
* 4. For each query, the script checks whether it matches or contains any of the | |
* branded keywords you specified. If a query does not contain a branded | |
* keyword, it's considered a non-branded keyword. | |
* | |
* 5. Non-branded keywords are added to a negative keyword list with the specified | |
* negative match type. If the list doesn't exist, the script creates it. | |
* | |
* 6. By periodically running this script, you automate the process of identifying | |
* and adding non-branded keywords to your negative list. This helps focus your | |
* ads on queries related to your brand, reducing irrelevant clicks and | |
* potentially improving your Google Shopping campaigns' ROI. | |
* | |
* It's important to keep in mind you can only have up to 20 negative keywords list, | |
* and each one is limited to 5000 keywords. | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
***********************************************************************************/ | |
// Configuration | |
const CONFIG = { | |
BRANDKWDS: ['brand name', 'brandname', 'braname'], | |
LISTNAME: 'MY_SUPER_NEG_LIST', | |
NEGMATCHTYPE: 'EXACT', | |
TIMERANGE: 'LAST_7_DAYS', | |
CAMPNAME: 'MY_CAMPAIGN_NAME', | |
}; | |
function main() { | |
var campaigns = AdsApp.shoppingCampaigns() | |
.withCondition("Status = ENABLED") | |
.withCondition("Name CONTAINS_IGNORE_CASE '" + CONFIG.CAMPNAME + "'") | |
.get(); | |
var negativeKeywordList = getOrCreateNegativeKeywordList(CONFIG.LISTNAME); | |
while (campaigns.hasNext()) { | |
var campaign = campaigns.next(); | |
Logger.log("Getting Search Terms report for campaign: " + campaign.getName()); | |
var report = AdsApp.report( | |
"SELECT Query " + | |
"FROM SEARCH_QUERY_PERFORMANCE_REPORT " + | |
"WHERE CampaignId = " + campaign.getId() + | |
" AND Cost > 0 " + | |
" DURING " + CONFIG.TIMERANGE | |
); | |
var rows = report.rows(); | |
while (rows.hasNext()) { | |
var row = rows.next(); | |
var query = row['Query']; | |
if (!isBranded(query, CONFIG.BRANDKWDS)) { | |
addNegativeKeyword(negativeKeywordList, query, CONFIG.NEGMATCHTYPE); | |
} | |
} | |
} | |
} | |
function getOrCreateNegativeKeywordList(ListName) { | |
var negativeKeywordLists = AdsApp.negativeKeywordLists() | |
.withCondition("Name = '" + ListName + "'") | |
.get(); | |
if (negativeKeywordLists.hasNext()) { | |
return negativeKeywordLists.next(); | |
} else { | |
Logger.log("Creating new negative keyword list: " + CONFIG.LISTNAME); | |
return AdsApp.newNegativeKeywordListBuilder() | |
.withName(CONFIG.LISTNAME) | |
.build() | |
.getResult(); | |
} | |
} | |
function isBranded(query) { | |
for (var i = 0; i < CONFIG.BRANDKWDS.length; i++) { | |
if (query.toLowerCase().indexOf(CONFIG.BRANDKWDS[i].toLowerCase()) > -1) { | |
return true; | |
} | |
} | |
return false; | |
} | |
function addNegativeKeyword(negativeKeywordList, keyword, NegMatchType) { | |
if(NegMatchType === 'EXACT') { | |
negativeKeywordList.addNegativeKeyword('[' + keyword + ']'); | |
} | |
else if(NegMatchType === 'BROAD') { | |
negativeKeywordList.addNegativeKeyword(keyword); | |
} | |
else if(NegMatchType === 'PHRASE') { | |
negativeKeywordList.addNegativeKeyword('"' + keyword + '"'); | |
} | |
else { | |
Logger.log("Invalid NegMatchType. Choose either EXACT, BROAD, or PHRASE."); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment