Als onderdeel van de kwaliteitsscore die elk zoekwoord in je account toegewezen krijgt, worden een aantal statistieken gebruikt die je terug kan vinden in je account. Het gaat dan om de volgende metrics:
In het config-gedeelte van het script, kan je meerdere waarden aanpassen naar wens.
LOG: Wijzig dit in 'true' om te zien wat er precies gebeurd. Laat op 'false' staan wanneer het script echt draait, want dat gaat sneller.
THRESHOLD_IMPRESSIONS: wijzig dit aantal als je van mening bent dat je meer vertoningen nodig hebt om goede statistieken te kunnen verzamelen.
DATE_RANGE: Heeft effect op de voorgaande variabele. Het script kijkt naar het aantal impressies in het gespecificeerde tijdsvak.
ACCOUNT_LABEL: Gebruik deze om specifieke accounts te selecteren.
KEYWORD_LABEL: Wordt op elk zoekwoord toegepast wanneer deze is opgenomen in de sheet, om dubbelen te voorkomen. Deze kan je naar wens aanpassen, het script maakt het label aan wanneer deze niet bestaat.
THRESHOLD_BOUNCE: Het zoekwoord moet minimaal deze bouncerate hebben om gerapporteerd te worden.
THRESHOLD_TOS: Het zoekwoord mag maximaal deze time on site (in seconden) hebben om gerapporteerd te worden.
SPREADSHEET_URL: Maak een kopie van deze spreadsheet en vul de URL hier in, om de resultaten van het script in te zetten.
MCC niveau
Onderstaand script kan gebruikt worden op MCC-niveau, zodat je per account een tabblad in een Google Sheet krijgt met daarin de zoekwoorden waar je verbeteringen bij kan doorvoeren. Bij de accountSelector filter ik alle accounts die het label 'Active' krijgen in je MCC. Als je dit niet wilt, kan je regel 43 verwijderen uit het script. Daarnaast wordt er aan elk zoekwoord een label gehangen, wanneer ze in het rapport worden opgenomen. Hierdoor komen zoekwoorden niet meerdere keren terug in de sheet.
Frequentie: Draai dit script elk uur, want het kan even duren voordat alle zoekwoorden van alle accounts doorlopen zijn.
The script
// Copyright 2020. Increase BV. All Rights Reserved.
// Not to be used without permission of the creator or Increase B.V.
//
// Created By: Tibbe van Asten
// for Increase B.V.
//
// Created: 29-11-2018
// Last update: 17-08-2020
//
// 17-08-2020: Added Keyword Match Type (idea by Arjan Schoorl)
//
// ABOUT THE SCRIPT
// With this script, we will create a report with all keywords
// in your accounts that have quality issues.
//
// Link to script: https://adsscripts.com/scripts/google-ads-scripts/report-keyword-quality
//
// ------------------------------------------------------------
// Script settings
var config = {
LOG : false,
THRESHOLD_IMPRESSIONS : 20,
DATE_RANGE : "LAST_30_DAYS",
ACCOUNT_LABEL : "Active",
KEYWORD_LABEL : "Keyword - Quality - Issue",
THRESHOLD_BOUNCE : 80,
THRESHOLD_TOS : 20,
// Copy from http://tinyurl.com/y536ld89
SPREADSHEET_URL : "XXX",
API_VERSION : "v201809"
}
// ------------------------------------------------------------
function main() {
var ss = connectSheet();
// Selecting all Ads Accounts
var accountIterator = AdsManagerApp
.accounts()
.withCondition("LabelNames CONTAINS '" + config.ACCOUNT_LABEL + "'")
.get();
while(accountIterator.hasNext()){
var account = accountIterator.next();
MccApp.select(account);
Logger.log("Account: " + account.getName());
Logger.log("-----");
// Create a label when it doesn't already exists
keywordLabel(account);
var label = AdsApp.labels().withCondition("Name = '" + config.KEYWORD_LABEL + "'").get().next();
// Check if a sheet already exists for this account
var sheet = checkSheet(ss, account);
// Selecting all keywords
var report = AdsApp.report(
"SELECT AccountDescriptiveName, CampaignName, AdGroupName, AdGroupId, Criteria, KeywordMatchType, Id, BounceRate, AverageTimeOnSite, FinalUrls, CpcBid, SearchPredictedCtr, CreativeQualityScore, HistoricalLandingPageQualityScore, Clicks " +
"FROM KEYWORDS_PERFORMANCE_REPORT " +
"WHERE LabelIds CONTAINS_NONE [" + label.getId() + "] " +
"AND CampaignStatus = ENABLED " +
"AND AdGroupStatus = ENABLED " +
"AND Status = ENABLED " +
"AND Impressions > " + config.THRESHOLD_IMPRESSIONS +
" DURING " + config.DATE_RANGE
);
var rows = report.rows();
while (rows.hasNext()) {
var row = rows.next();
reportRows(row, sheet);
} // row iterator
Logger.log(account.getName() + " afgerond");
} // account iterator
} // function main()
// ------------------------------------------------------------
function reportRows(row, sheet){
// Checking a couple of variables, to make sure everything works as expected
var bounceRate = checkBounce(row);
var tos = checkTos(row)
if((tos < config.THRESHOLD_TOS && tos != "") || bounceRate > config.THRESHOLD_BOUNCE || row["SearchPredictedCtr"] == "Below average" || row["CreativeQualityScore"] == "Below average" || row["HistoricalLandingPageQualityScore"] == "Below average"){
if(config.LOG == true){
Logger.log("Keyword: " + row["Criteria"]);
Logger.log("TOS: " + row["AverageTimeOnSite"]);
Logger.log("Bounce: " + row["BounceRate"]);
Logger.log("Ad Quality: " + row["CreativeQualityScore"]);
Logger.log("LP Experience: " + row["HistoricalLandingPageQualityScore"]);
Logger.log("Exp. CTR: " + row["SearchPredictedCtr"]);
Logger.log(" ");
}
// Checking the final URL of a keyword. If not set, we will find the URL of the best performing ad in the adgroup
var finalUrl = findUrl(row);
// Now we put all the info in the sheet
sheet.appendRow([row["AccountDescriptiveName"],row["CampaignName"],row["AdGroupName"],row["AdGroupId"],"'" + row["Criteria"],row["KeywordMatchType"],row["Id"],bounceRate,row["CreativeQualityScore"],row["HistoricalLandingPageQualityScore"],row["SearchPredictedCtr"],tos,row["CpcBid"],finalUrl]);
// Label the keyword, so we know it's processed
labelKeywords(row["AdGroupId"], row["Id"]);
} // keyword selection
} // function reportRows
// ------------------------------------------------------------
function findUrl(row){
if(row["FinalUrls"] == "--"){
var keywordIterator = AdsApp
.keywords()
.withIds([[row["AdGroupId"], row["Id"]]])
.get();
while(keywordIterator.hasNext()){
var keyword = keywordIterator.next();
var finalUrl = keyword.getAdGroup().ads().orderBy("Ctr DESC").forDateRange(config.DATE_RANGE).withLimit(1).get().next().urls().getFinalUrl();
} // keyword iterator
} else {
var finalUrl = row["FinalUrls"];
}
return finalUrl;
} // function findUrl()
// ------------------------------------------------------------
function checkBounce(row){
if(row["Clicks"] >= 10){
var bounceRate = parseInt(row["BounceRate"]);
} else {
var bounceRate = "";
}
return bounceRate;
} // checkBounce()
// ------------------------------------------------------------
function checkTos(row){
if(row["Clicks"] >= 10){
var tos = parseInt(row["AverageTimeOnSite"]);
} else {
var tos = "";
}
return tos;
} // function checkTos()
// ------------------------------------------------------------
function keywordLabel(account){
if(!AdsApp.labels().withCondition("Name = '"+config.KEYWORD_LABEL+"'").get().hasNext()) {
AdsApp.createLabel(config.KEYWORD_LABEL);
if(config.LOG == true){
Logger.log("Label " + config.KEYWORD_LABEL + " created");
}
}
} // function keywordLabel()
// ------------------------------------------------------------
function labelKeywords(adGroupId, keywordId){
var keywordIterator = AdsApp
.keywords()
.withIds([[adGroupId, keywordId]])
.get();
while(keywordIterator.hasNext()){
var keyword = keywordIterator.next();
keyword.applyLabel(config.KEYWORD_LABEL);
if(config.LOG == true){
Logger.log("Label toegepast op " + keyword.getText());
Logger.log(" ");
}
} // keyword iterator
} // function labelKeywords
// ------------------------------------------------------------
function connectSheet(){
var ss = SpreadsheetApp.openByUrl(config.SPREADSHEET_URL);
return ss;
} // function connectSheet()
// ------------------------------------------------------------
function checkSheet(ss, account){
var sheet = ss.getSheetByName(account.getName());
if (sheet == null) {
var templateSheet = ss.getSheetByName("Template");
ss.insertSheet(account.getName(), {template: templateSheet});
var sheet = ss.getSheetByName(account.getName());
Logger.log("New sheet created for " + account.getName());
} // if sheet doesn't exists
return sheet;
} // checkSheet()
Show whole script!
Loading Comments
The Experts
Tibbe van AstenTeam Lead Performance Marketing
Nils RooijmansWater Cooler Topics
Martijn KraanFreelance PPC Specialist
Bas BaudoinTeamlead SEA @ Happy Leads
Jermaya LeijenDigital Marketing Strategist
Krzysztof BycinaPPC Specialist from Poland
How about you?JOIN US!
Caring
Adsscripts.com staat voor het delen van kennis. In de huidige markt houden SEA-specialisten de kennis en ervaring graag voor zich. Wij zijn er van overtuigd dat het delen van kennis ervoor kan zorgen dat iedereen beter wordt in haar of zijn werk. Daarom lopen wij hier graag in voorop, door onze kennis over scripts te delen met iedereen.
Wil jij ook graag een bijdrage leveren? Wij staan open voor nieuwe ideeën en feedback op alles wat je op Adsscripts.com vindt.