August 17, 2017
AdWords Scripts: Keep DSA campaigns clean
Automatically optimize DSA campaigns with this script.
Dynamic Search Ads (DSA) in AdWords can be a great support in sourcing keywords and shouldn’t be missing in a typical account. With DSA, Google will automagically play ads for search phrases depending on what it understands from your website. As we are talking about Google this is usually very good and precise.
However, in an optimized account you will only want DSA to be a fallback and target all relevant queries explicitly with keywords and perfectly fitting ads. During that process of squeezing keywords out of DSA it can occasionally occur that search traffic overlaps as regular campaigns as well as DSA campaigns target the same set of keywords because negative keywords weren’t accurately managed. Although this is often not a serious problem, in bad scenarios search terms may be served through DSA that otherwise would get a way lower cpc and budget. Hence, it’s recommended to have a clean account with distinct traffic slices, meaning impressions + clicks + cost for a specific search phrase should accumulate in one single place.
Therefore, meet this little AdWords Script which will compare your DSA search queries with queries from other places in your account by utilizing AWQL reports. If it detects duplicate queries it will add the respective query as [exact negative] in your DSA campaign, thus making your regular campaign the only source of control, and especially of the cpc. Within this script a DSA campaign is simply identified by having DSA in its name.
function main() {
var queryReport = AdWordsApp.report(
"SELECT CampaignName,AdGroupName, AdGroupId, Query, Clicks, Impressions " +
"FROM SEARCH_QUERY_PERFORMANCE_REPORT " +
"WHERE Clicks > 0 " +
"AND CampaignName DOES_NOT_CONTAIN_IGNORE_CASE 'Shopping' " +
"AND CampaignStatus = ENABLED " +
"AND AdGroupStatus = ENABLED " +
"DURING LAST_7_DAYS" ).rows();
var collect = {};
while( queryReport.hasNext() ) {
var r= queryReport.next();
if( typeof( collect[r.Query] ) === "undefined" ) {
collect[r.Query] = {
"other": 0,
"dsa": { "impressions" : 0, agIds: [] }
};
}
if( r.CampaignName.indexOf( "DSA" ) != -1 ) {
collect[r.Query].dsa.impressions += parseInt( r.Impressions );
if( collect[r.Query].dsa.agIds.indexOf( r.AdGroupId ) == -1 )
collect[r.Query].dsa.agIds.push( r.AdGroupId );
}
else {
collect[r.Query].other += parseInt( r.Impressions );
}
}
for( query in collect ) {
if( collect[query].dsa.impressions == 0 )
continue;
else if( collect[query].other > 0 ) {
for( i in collect[query].dsa.agIds ) {
var ag = AdWordsApp.adGroups().withIds([parseInt(collect[query].dsa.agIds[i])]).get().next().createNegativeKeyword( "["+ query +"]" );
}
}
}
}