Snippets

Frederick Vallaeys Ad Text Report With Keyword and QS Data

Updated by Frederick Vallaeys

File snippet.js Modified

  • Ignore whitespace
  • Hide word diff
   }
     
 
-  Logger.log("Here is the spreadsheet with results: " + spreadsheet.url);
+  Logger.log("Here is the spreadsheet with results: " + spreadsheetUrl);
   
   /*    
   var spreadsheet = SpreadsheetApp.openByUrl(spreadsheetUrl).getSheetByName("by account");
Updated by Frederick Vallaeys

File snippet.js Modified

  • Ignore whitespace
  • Hide word diff
   }
     
 
-  Logger.log("Here is the spreadsheet with results: " + spreadsheet.getUrl());
+  Logger.log("Here is the spreadsheet with results: " + spreadsheet.url);
   
   /*    
   var spreadsheet = SpreadsheetApp.openByUrl(spreadsheetUrl).getSheetByName("by account");
Updated by Frederick Vallaeys

File snippet.js Modified

  • Ignore whitespace
  • Hide word diff
       }
     }
   }
-      
+    
+
+  Logger.log("Here is the spreadsheet with results: " + spreadsheet.getUrl());
+  
   /*    
   var spreadsheet = SpreadsheetApp.openByUrl(spreadsheetUrl).getSheetByName("by account");
   var spreadsheetOutput = new Array();
         }
       }
     }
-    Logger.log("Here is the spreadsheet with results: " + destinationSpreadsheet);
     return(destinationSpreadsheet);
   }
Updated by Frederick Vallaeys

File snippet.js Modified

  • Ignore whitespace
  • Hide word diff
         }
       }
     }
+    Logger.log("Here is the spreadsheet with results: " + destinationSpreadsheet);
     return(destinationSpreadsheet);
   }
Updated by Frederick Vallaeys

File snippet.js Modified

  • Ignore whitespace
  • Hide word diff
-  var DEBUG = 0;
+/*
+
+This script generates a spreadsheet with recommendations for ways to fix QS
+
+Here's what you need to know about the resulting spreadsheet:
+
+· For the ad components, any field that is red indicates below average score (i.e. ad text is below avg or LP is below avg)
+
+· The numbers in column C indicate which keywords to keep together in new ad groups because they had the same QS issues.
+
+· You can filter on column AB where the value is 1 to discover the best performing ad from the ad group. We simply select the best CTR version but you could go into the code to change how the best ad variation is selected.
+
+· Column AA indicates if there was any ad testing happening. If the value is 0, it means that the best ad text we suggest is only the best because there were no others to choose from
+
+
+
+*/
+
+var currentSetting = new Object();
+var DEBUG = 1;
+
+currentSetting.showAll = 1;
 
 function main() {
   
   
   var spreadsheetUrl = "";
   var spreadsheetName = "KW Ad Data";
-  var accountManagers = "example@example.com";
+  var accountManagers = "frederick@optmyzr.com";
   var overWriteOldData = 1;
-  var sheetNames = ["data"];
+  var sheetNames = ["by ad group"]; //var sheetNames = ["by ad group", "by account"];
   
   var destinationSpreadsheet = setUpReportInGoogleSheets(spreadsheetUrl, spreadsheetName, accountManagers, overWriteOldData, sheetNames);
   var spreadsheet = destinationSpreadsheet.spreadsheet;
   var isSpreadsheetNew = destinationSpreadsheet.isNew;
   var spreadsheetUrl = destinationSpreadsheet.url;
 
-  var keywordIdMap = buildKeywordIdMap();
-  var adGroupMap = buildAdGroupMap();
+  var maps = buildKeywordIdMap();
+  var keywordIdMap = maps.keywordIdMap;
+  var adGroupMap = maps.adGroupMap;
+  var maps = buildAdMap();
+  //var adMap = maps.adMap;
+  //var keywordAdMap = maps.keywordAdMap;
+  var accountMap = maps.accountMap;
+  var keywordAdMapByAG = maps.keywordAdMapByAG;
+  //var keywordAdMap = buildKeywordAdMap();
+  
+  var newAdGroupCounter = 1;
+  
+  var spreadsheet = SpreadsheetApp.openByUrl(spreadsheetUrl).getSheetByName("by ad group");
+  var spreadsheetOutput = new Array();
+  spreadsheet.appendRow(["Campaign Name", "Ad Group Name", "New Ad Group Counter", "keywordId", "keywordText", "keywordMatchType", "adId", "headline", "description1", "description2", "displayUrl", "creativeFinalUrls", "devicePreference", "clicks", "impressions", "ctr", "qualityScore", "creativeQualityScore", "postClickQualityScore", "searchPredictedCtr", "KW bounceRate", "KW averagePageviews", "KW averageTimeOnSite", "adBounceRate", "adAveragePageviews", "adAverageTimeOnSite", "numOtherAdsForKeyword", "best?" ]);
+  spreadsheet.setFrozenRows(1);
   
+  
+  for(var campaignId in accountMap.campaigns) {
+    var campaign = accountMap.campaigns[campaignId];
+    var campaignName = campaign.campaignName;
+    //Logger.log("CN: " + campaignName);
+    
+    for(var adGroupId in campaign.adGroups) {
+      var adGroup = campaign.adGroups[adGroupId];
+      var adGroupName = adGroup.adGroupName;
+      //Logger.log("  AGN: " + adGroupName);
+      
+      for(var adId in adGroup.ads) {
+        
+        var keywordsExistForThisNewAdGroup = 0;
+        var spreadsheetLine = new Array();
+        var ad = adGroup.ads[adId];
+        
+        var headline = ad.headline;
+        var description1 = ad.description1;
+        var description2 = ad.description2;
+        var devicePreference = ad.devicePreference;
+        var displayUrl = ad.displayUrl;
+        var creativeFinalUrls = ad.creativeFinalUrls;
+        
+        var adBounceRate = ad.bounceRate;
+        var adAveragePageviews = ad.averagePageviews;
+        var adAverageTimeOnSite = ad.averageTimeOnSite;
+        
+        for(var keywordId in ad.keywords) {
+          var keyword = ad.keywords[keywordId];
+          var clicks = keyword.clicks;
+          var impressions = keyword.impressions;
+          var ctr = keyword.ctr;
+          //var bounceRate = keyword.bounceRate;
+          //var averagePageViews = keyword.averagePageViews;
+          //var averageTimeOnSite = keyword.averageTimeOnSite;
+          try {
+            var keywordText = keywordIdMap[keywordId].keywordText;
+            var keywordMatchType = keywordIdMap[keywordId].keywordMatchType;
+            var qualityScore = keywordIdMap[keywordId].qualityScore;
+            var creativeQualityScore = keywordIdMap[keywordId].creativeQualityScore;
+            var postClickQualityScore = keywordIdMap[keywordId].postClickQualityScore;
+            var searchPredictedCtr = keywordIdMap[keywordId].searchPredictedCtr;
+            if(keywordText[0] == "+") keywordText = "'" + keywordText;
+            var keywordBounceRate = adGroupMap[adGroupId].keywords[keywordId].bounceRate;
+            var keywordAveragePageviews = adGroupMap[adGroupId].keywords[keywordId].averagePageviews;
+            var keywordAverageTimeOnSite = adGroupMap[adGroupId].keywords[keywordId].averageTimeOnSite;
+          } catch (e) {
+            var keywordText = "N/A";
+            var keywordMatchType = "N/A";
+            var qualityScore = "--";
+            var creativeQualityScore = "--";
+            var postClickQualityScore = "--";
+            var searchPredictedCtr = "--";
+            var keywordBounceRate = "--";
+            var keywordAveragePageViews = "--";
+            var keywordAverageTimeOnSite = "--";
+          }
+          try {
+            var uniqueId = adGroupId + " " + keywordId;
+            var bestAdId = keywordAdMapByAG[uniqueId].bestAdId;
+            var otherAds = keywordAdMapByAG[uniqueId].ads;
+            var numOtherAdsForKeyword = otherAds.length - 1;
+            //Logger.log("numOtherAdsForKeyword: " + numOtherAdsForKeyword);
+            if(bestAdId == adId) {
+              var isThisBestAd = 1;
+            } else {
+              var isThisBestAd = 0;
+            }
+          } catch (e) {
+            Logger.log("Error with getting other ads for keyword: " + e); 
+          }
+          //spreadsheetLine.push(keywordText, campaignName, adGroupName, headline, description1, description2, clicks, impressions, ctr);
+          
+          // Find all the keywords that share this as the best ad (when the keyword tested multiple ad variants)
+          //if(numOtherAdsForKeyword > 0 && isThisBestAd && (creativeQualityScore.toLowerCase().indexOf("below") != -1 || postClickQualityScore.toLowerCase().indexOf("below") != -1)) {
+          if(currentSetting.showAll > 0 || (isThisBestAd && (creativeQualityScore.toLowerCase().indexOf("below") != -1 || postClickQualityScore.toLowerCase().indexOf("below") != -1))) {
+            // numOtherAdsForKeyword > 0 && 
+            if(adGroupMap[adGroupId].countOfCreativeQualityScoreAboveAverage > 0 || adGroupMap[adGroupId].countOfCreativeQualityScoreAverage > 0 || adGroupMap[adGroupId].countOfPostClickQualityScoreAboveAverage > 0 || adGroupMap[adGroupId].countOfPostClickQualityScoreAverage > 0) {
+              if(creativeQualityScore.toLowerCase().indexOf("below") != -1 && postClickQualityScore.toLowerCase().indexOf("below") != -1) {
+                // condition 1
+                var newAdGroupId = newAdGroupCounter;
+              } else if(creativeQualityScore.toLowerCase().indexOf("below") != -1) {
+                // condition 2
+                var newAdGroupId = newAdGroupCounter + 1;
+              } else if (postClickQualityScore.toLowerCase().indexOf("below") != -1) {
+                // condition 3
+                var newAdGroupId = newAdGroupCounter + 2;
+              }
+              
+              //var newAdGroupId = newAdGroupCounter;
+              var keywordsExistForThisNewAdGroup = 1;
+            } else {
+              var newAdGroupId = "0";
+            }
+            spreadsheet.appendRow([campaignName, adGroupName, newAdGroupId, keywordId, keywordText, keywordMatchType, adId, headline, description1, description2, displayUrl, creativeFinalUrls, devicePreference, clicks, impressions, ctr, qualityScore, creativeQualityScore, postClickQualityScore, searchPredictedCtr, keywordBounceRate, keywordAveragePageviews, keywordAverageTimeOnSite, adBounceRate, adAveragePageviews, adAverageTimeOnSite, numOtherAdsForKeyword, isThisBestAd ]);
+            // color the cells
+            if(postClickQualityScore.toLowerCase().indexOf("below") != -1) {
+              var thisRow = spreadsheet.getLastRow();
+              //Logger.log("thisRow: " + thisRow);
+              spreadsheet.getRange("L" + thisRow).setBackgroundRGB(255, 217, 215);
+            }
+            if(creativeQualityScore.toLowerCase().indexOf("below") != -1) {
+              var thisRow = spreadsheet.getLastRow();
+              spreadsheet.getRange("H" + thisRow + ":K" + thisRow).setBackgroundRGB(255, 217, 215);
+            }
+            
+          } 
+          //Logger.log("kwtext: " + keywordText + " ag: " + adGroupName + " cn: " + campaignName + " Ad: " + headline + " " + description1 + " " + description2 + " imp: " + impressions);
+        }
+        if(keywordsExistForThisNewAdGroup) newAdGroupCounter += 3;
+      }
+    }
+  }
+      
+  /*    
+  var spreadsheet = SpreadsheetApp.openByUrl(spreadsheetUrl).getSheetByName("by account");
   var spreadsheetOutput = new Array();
-  spreadsheet.appendRow(["keywordText", "keywordMatchType", "campaignName", "adGroupName", "headline", "description1", "description2", "displayUrl", "devicePreference", "clicks", "impressions", "ctr", "qualityScore", "creativeQualityScore", "postClickQualityScore", "searchPredictedCtr" ]);
-  for(var uniqueId in adGroupMap) {
+  spreadsheet.appendRow(["Campaign Name", "Ad Group Name", "New Ad Group Counter", "keywordId", "keywordText", "keywordMatchType", "adId", "headline", "description1", "description2", "displayUrl", "creativeFinalUrls", "devicePreference", "clicks", "impressions", "ctr", "qualityScore", "creativeQualityScore", "postClickQualityScore", "searchPredictedCtr", "numOtherAdsForKeyword", "best?" ]);
+  
+  for(var adId in adMap) {
+    var keywordsExistForThisNewAdGroup = 0;
     var spreadsheetLine = new Array();
-    var adGroup = adGroupMap[uniqueId];
-    var campaignName = adGroup.campaignName;
-    var adGroupName = adGroup.adGroupName;
-    for(var adId in adGroup.ads) {
-      var ad = adGroup.ads[adId];
-      var headline = ad.headline;
-      var description1 = ad.description1;
-      var description2 = ad.description2;
-      var devicePreference = ad.devicePreference;
-      var displayUrl = ad.displayUrl;
-      for(var keywordId in ad.keywords) {
-        var keyword = ad.keywords[keywordId];
-        var clicks = keyword.clicks;
-        var impressions = keyword.impressions;
-        var ctr = keyword.ctr;
-        try {
-          var keywordText = keywordIdMap[keywordId].keywordText;
-          var keywordMatchType = keywordIdMap[keywordId].keywordMatchType;
-          var qualityScore = keywordIdMap[keywordId].qualityScore;
-          var creativeQualityScore = keywordIdMap[keywordId].creativeQualityScore;
-          var postClickQualityScore = keywordIdMap[keywordId].postClickQualityScore;
-          var searchPredictedCtr = keywordIdMap[keywordId].searchPredictedCtr;
-          if(keywordText[0] == "+") keywordText = "'" + keywordText;
-        } catch (e) {
-          var keywordText = "N/A";
-          var keywordMatchType = "N/A";
-          var qualityScore = "--";
-          var creativeQualityScore = "--";
-          var postClickQualityScore = "--";
-          var searchPredictedCtr = "--";
+    var ad = adMap[adId];
+    
+    var headline = ad.headline;
+    var description1 = ad.description1;
+    var description2 = ad.description2;
+    var devicePreference = ad.devicePreference;
+    var displayUrl = ad.displayUrl;
+    var creativeFinalUrls = ad.creativeFinalUrls;
+    
+    for(var keywordId in ad.keywords) {
+      var keyword = ad.keywords[keywordId];
+      var clicks = keyword.clicks;
+      var impressions = keyword.impressions;
+      var ctr = keyword.ctr;
+      try {
+        var keywordText = keywordIdMap[keywordId].keywordText;
+        var keywordMatchType = keywordIdMap[keywordId].keywordMatchType;
+        var qualityScore = keywordIdMap[keywordId].qualityScore;
+        var creativeQualityScore = keywordIdMap[keywordId].creativeQualityScore;
+        var postClickQualityScore = keywordIdMap[keywordId].postClickQualityScore;
+        var searchPredictedCtr = keywordIdMap[keywordId].searchPredictedCtr;
+        if(keywordText[0] == "+") keywordText = "'" + keywordText;
+      } catch (e) {
+        var keywordText = "N/A";
+        var keywordMatchType = "N/A";
+        var qualityScore = "--";
+        var creativeQualityScore = "--";
+        var postClickQualityScore = "--";
+        var searchPredictedCtr = "--";
+      }
+      try {
+        var otherAdsForKeyword = keywordAdMap[keywordId].ads;
+        var bestAdId = keywordAdMap[keywordId].bestAdId;
+        if(bestAdId == adId) {
+          var isThisBestAd = 1;
+        } else {
+          var isThisBestAd = 0;
         }
+        var numOtherAdsForKeyword = otherAdsForKeyword.length - 1;
+        //Logger.log("numOtherAdsForKeyword: " + numOtherAdsForKeyword);
+      } catch (e) {
+        Logger.log("Error with getting other ads for keyword: " + e); 
       }
+      //spreadsheetLine.push(keywordText, campaignName, adGroupName, headline, description1, description2, clicks, impressions, ctr);
+      
+      // Find all the keywords that share this as the best ad (when the keyword tested multiple ad variants)
+      
+      if(currentSetting.showAll || (numOtherAdsForKeyword > 0 && isThisBestAd && (creativeQualityScore.toLowerCase().indexOf("below") != -1 || postClickQualityScore.toLowerCase().indexOf("below") != -1))) {
+        spreadsheet.appendRow([newAdGroupCounter, keywordId, keywordText, keywordMatchType, adId, headline, description1, description2, displayUrl, creativeFinalUrls, devicePreference, clicks, impressions, ctr, qualityScore, creativeQualityScore, postClickQualityScore, searchPredictedCtr, numOtherAdsForKeyword, isThisBestAd ]);
+        var keywordsExistForThisNewAdGroup = 1;
+      }
+      //Logger.log("kwtext: " + keywordText + " ag: " + adGroupName + " cn: " + campaignName + " Ad: " + headline + " " + description1 + " " + description2 + " imp: " + impressions);
+    }
+    if(keywordsExistForThisNewAdGroup) newAdGroupCounter++;
+  }
+  
+  
+  // STEP 2: Suggest New Ad Groups For Keywords That Did NOT do ad testing
+  for(var adId in adMap) {
+    var keywordsExistForThisNewAdGroup = 0;
+    var spreadsheetLine = new Array();
+    var ad = adMap[adId];
+    
+    var headline = ad.headline;
+    var description1 = ad.description1;
+    var description2 = ad.description2;
+    var devicePreference = ad.devicePreference;
+    var displayUrl = ad.displayUrl;
+    var creativeFinalUrls = ad.creativeFinalUrls;
+    
+    for(var keywordId in ad.keywords) {
+      var keyword = ad.keywords[keywordId];
+      var clicks = keyword.clicks;
+      var impressions = keyword.impressions;
+      var ctr = keyword.ctr;
+      try {
+        var keywordText = keywordIdMap[keywordId].keywordText;
+        var keywordMatchType = keywordIdMap[keywordId].keywordMatchType;
+        var qualityScore = keywordIdMap[keywordId].qualityScore;
+        var creativeQualityScore = keywordIdMap[keywordId].creativeQualityScore;
+        var postClickQualityScore = keywordIdMap[keywordId].postClickQualityScore;
+        var searchPredictedCtr = keywordIdMap[keywordId].searchPredictedCtr;
+        if(keywordText[0] == "+") keywordText = "'" + keywordText;
+      } catch (e) {
+        var keywordText = "N/A";
+        var keywordMatchType = "N/A";
+        var qualityScore = "--";
+        var creativeQualityScore = "--";
+        var postClickQualityScore = "--";
+        var searchPredictedCtr = "--";
+      }
+      try {
+        var otherAdsForKeyword = keywordAdMap[keywordId].ads;
+        var bestAdId = keywordAdMap[keywordId].bestAdId;
+        if(bestAdId == adId) {
+          var isThisBestAd = 1;
+        } else {
+          var isThisBestAd = 0;
+        }
+        var numOtherAdsForKeyword = otherAdsForKeyword.length - 1;
+        //Logger.log("numOtherAdsForKeyword: " + numOtherAdsForKeyword);
+      } catch (e) {
+        Logger.log("Error with getting other ads for keyword: " + e); 
+      }
+      //spreadsheetLine.push(keywordText, campaignName, adGroupName, headline, description1, description2, clicks, impressions, ctr);
+      
+      if(currentSetting.showAll || (numOtherAdsForKeyword == 0 && (creativeQualityScore.toLowerCase().indexOf("below") != -1 || postClickQualityScore.toLowerCase().indexOf("below") != -1))) {
+        spreadsheet.appendRow([newAdGroupCounter, keywordId, keywordText, keywordMatchType, adId, headline, description1, description2, displayUrl, creativeFinalUrls, devicePreference, clicks, impressions, ctr, qualityScore, creativeQualityScore, postClickQualityScore, searchPredictedCtr, numOtherAdsForKeyword, isThisBestAd ]);
+        if(postClickQualityScore.toLowerCase().indexOf("below") != -1) {
+          var thisRow = spreadsheet.getLastRow();
+          //Logger.log("thisRow: " + thisRow);
+          spreadsheet.getRange("J" + thisRow).setBackground("red");
+        }
+        if(creativeQualityScore.toLowerCase().indexOf("below") != -1) {
+          var thisRow = spreadsheet.getLastRow();
+          spreadsheet.getRange("F" + thisRow).setBackground("red");
+        }
+        newAdGroupCounter++
+      }
+      //Logger.log("kwtext: " + keywordText + " ag: " + adGroupName + " cn: " + campaignName + " Ad: " + headline + " " + description1 + " " + description2 + " imp: " + impressions);
     }
   }
+  */
+  
+  
 }
 
-function buildAdGroupMap() {
-  var adGroupMap = new Array();
+
+
+function buildAdMap() {
+  var accountMap = new Array();
+  var adMap = new Array();
+  var keywordAdMap = new Array();
+  var keywordAdMapByAG = new Array();
   var report = AdWordsApp.report(
-    'SELECT Id, CampaignName, AdGroupName, KeywordId, DevicePreference, Headline, Description1, Description2, DisplayUrl, Clicks, Impressions, Ctr ' +
+    'SELECT Id, CampaignName, AdGroupName, CampaignId, AdGroupId, KeywordId, DevicePreference, Headline, Description1, Description2, DisplayUrl, CreativeFinalUrls, Clicks, Impressions, Ctr, BounceRate, AverageTimeOnSite, AveragePageviews ' +
     'FROM   AD_PERFORMANCE_REPORT ' +
-    'WHERE  Impressions > 10 ' +
+    'WHERE  Impressions >= 0 ' +
     'AND AdType = "TEXT_AD" ' +
     'DURING LAST_30_DAYS');
   
+  // Build Account Map (By campaign and ad group)
   var rows = report.rows();
   while (rows.hasNext()) {
     var row = rows.next();
     var adId = row['Id'];
     var campaignName = row['CampaignName'];
     var adGroupName = row['AdGroupName'];
+    var campaignId = row['CampaignId'];
+    var adGroupId = row['AdGroupId'];
     var keywordId = row['KeywordId'];
     var devicePreference = row['DevicePreference'];
+    var ctr = parseFloat(row['Ctr']);
+    var impressions = parseInt(row['Impressions']);
+    var clicks = parseInt(row['Clicks']);
+    //var averagePageviews = parseInt(row['AveragePageviews']);
+    //var bounceRate = parseFloat(row['BounceRate']);
+    //var averageTimeOnSite = parseFloat(row['AverageTimeOnSite']);
+    //Logger.log("BR: " + bounceRate);
+    
+    if(!accountMap.campaigns) {
+      accountMap.campaigns = new Array();
+    }
+    
+    if(!accountMap.campaigns[campaignId]) {
+      accountMap.campaigns[campaignId] = new Object();
+      accountMap.campaigns[campaignId].campaignName = campaignName;
+      accountMap.campaigns[campaignId].adGroups = new Array();
+    }
+    
+    if(!accountMap.campaigns[campaignId].adGroups[adGroupId]) {
+      accountMap.campaigns[campaignId].adGroups[adGroupId] = new Object();
+      accountMap.campaigns[campaignId].adGroups[adGroupId].adGroupName = adGroupName;
+      accountMap.campaigns[campaignId].adGroups[adGroupId].ads = new Array();
+    }
     
-    var uniqueId = campaignName + " " + adGroupName;
-    if(!adGroupMap[uniqueId]) {
-      adGroupMap[uniqueId] = new Object();
-      adGroupMap[uniqueId].ads = new Array();
-      adGroupMap[uniqueId].campaignName = campaignName;
-      adGroupMap[uniqueId].adGroupName = adGroupName;
+    if(!accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId]) {
+      accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId] = new Object();
+      accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords = new Array();
     }
-    if(!adGroupMap[uniqueId].ads[adId]){
-      adGroupMap[uniqueId].ads[adId] = new Object();
-      adGroupMap[uniqueId].ads[adId].devicePreference = devicePreference;
-      adGroupMap[uniqueId].ads[adId].keywords = new Array();
+    
+    accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].headline = row['Headline'];
+    accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].description1 = row['Description1'];
+    accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].description2 = row['Description2'];
+    accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].displayUrl = row['DisplayUrl'];
+    accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].devicePreference = devicePreference;
+    accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].creativeFinalUrls = row['CreativeFinalUrls'];
+    
+    if(!accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId]) {
+      accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId] = new Object();
+      accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId].isBestAd = 0;
+      accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId].clicks = 0;
+      accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId].impressions = 0;
+      accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId].ctr = 0;
+    }
+    
+    accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId].keywordId = keywordId;
+    accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId].clicks += clicks;
+    accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId].impressions += impressions;
+    accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId].ctr = accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId].clicks / accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId].impressions;
+    //accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId].averageTimeOnSite = averageTimeOnSite;
+    //accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId].bounceRate = bounceRate;
+    //accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].keywords[keywordId].averagePageviews = averagePageviews;
+    
+    /*
+    // 1. BUILD AD MAP
+    var uniqueId = adId;
+    if(!adMap[uniqueId]) {
+      adMap[uniqueId] = new Object();
+      adMap[uniqueId].locationsInAccount = new Array();
+      adMap[uniqueId].keywords = new Array();
+    }
+    
+    adMap[uniqueId].headline = row['Headline'];
+    adMap[uniqueId].description1 = row['Description1'];
+    adMap[uniqueId].description2 = row['Description2'];
+    adMap[uniqueId].displayUrl = row['DisplayUrl'];
+    adMap[uniqueId].devicePreference = devicePreference;
+    adMap[uniqueId].creativeFinalUrls = row['CreativeFinalUrls'];
+    
+    
+    var thisLocationInAccount = new Object();
+    thisLocationInAccount.campaignName = campaignName;
+    thisLocationInAccount.adGroupName = adGroupName;
+    adMap[uniqueId].locationsInAccount.push(thisLocationInAccount);
+    
+    if(!adMap[uniqueId].keywords[keywordId]) {
+      adMap[uniqueId].keywords[keywordId] = new Object();
+    }
+    
+    adMap[uniqueId].keywords[keywordId].keywordId = keywordId;
+    adMap[uniqueId].keywords[keywordId].clicks = row['Clicks'];
+    adMap[uniqueId].keywords[keywordId].impressions = row['Impressions'];
+    adMap[uniqueId].keywords[keywordId].ctr = row['Ctr'];
+    
+    // 2. BUILD ACCOUNT WIDE KEYWORD AD MAP
+    
+    if(!keywordAdMap[keywordId]) {
+      keywordAdMap[keywordId] = new Object();
+      keywordAdMap[keywordId].ads = new Array();
+      keywordAdMap[keywordId].bestAdId = "";
+      keywordAdMap[keywordId].bestAdValue = -1;
     }
-    if(!adGroupMap[uniqueId].ads[adId].keywords[keywordId]) {
-      adGroupMap[uniqueId].ads[adId].keywords[keywordId] = new Object();
+    var thisAd = new Object();
+    thisAd.ctr = ctr;
+    thisAd.impressions = impressions;
+    thisAd.id = adId;
+    keywordAdMap[keywordId].ads.push(thisAd);
+    
+    var currentBestValue = keywordAdMap[keywordId].bestAdValue;
+    
+    //Logger.log("ctr: " + ctr);
+    //Logger.log("currentBestValue: " + currentBestValue);
+    
+    if(ctr >= currentBestValue) {
+      keywordAdMap[keywordId].bestAdId = adId;
+      keywordAdMap[keywordId].bestAdValue = ctr;
+      //Logger.log("new best ad found. ctr = " + ctr);
     }
-    adGroupMap[uniqueId].ads[adId].headline = row['Headline'];
-    adGroupMap[uniqueId].ads[adId].description1 = row['Description1'];
-    adGroupMap[uniqueId].ads[adId].description2 = row['Description2'];
-    adGroupMap[uniqueId].ads[adId].displayUrl = row['DisplayUrl'];
+    */
+    
+    // 3. BUILD AD GROUP KEYWORD AD MAP
+    
+    var uniqueId = adGroupId + " " + keywordId;
+    if(!keywordAdMapByAG[uniqueId]) {
+      keywordAdMapByAG[uniqueId] = new Object();
+      keywordAdMapByAG[uniqueId].ads = new Array();
+      keywordAdMapByAG[uniqueId].bestAdId = "";
+      keywordAdMapByAG[uniqueId].bestAdValue = -1;
+    }
+    var thisAd = new Object();
+    thisAd.ctr = ctr;
+    thisAd.impressions = impressions;
+    thisAd.id = adId;
+    keywordAdMapByAG[uniqueId].ads.push(thisAd);
+    
+    var currentBestValue = keywordAdMapByAG[uniqueId].bestAdValue;
     
+    //Logger.log("ctr: " + ctr);
+    //Logger.log("currentBestValue: " + currentBestValue);
+    
+    if(ctr >= currentBestValue) {
+      keywordAdMapByAG[uniqueId].bestAdId = adId;
+      keywordAdMapByAG[uniqueId].bestAdValue = ctr;
+      //Logger.log("new best ad found. ctr = " + ctr);
+    }
+  }
+  
+  // 4. Add GA Data to map (it's not segmentable by keyword)
+  var report = AdWordsApp.report(
+    'SELECT Id, CampaignId, AdGroupId, BounceRate, AverageTimeOnSite, AveragePageviews ' +
+    'FROM   AD_PERFORMANCE_REPORT ' +
+    'WHERE  Impressions >= 0 ' +
+    'AND AdType = "TEXT_AD" ' +
+    'DURING LAST_30_DAYS');
+  
+  
+  var rows = report.rows();
+  while (rows.hasNext()) {
+    var row = rows.next();
+    var adId = row['Id'];
+    var adGroupName = row['AdGroupName'];
+    var campaignId = row['CampaignId'];
+    var adGroupId = row['AdGroupId'];
+    var averagePageviews = parseInt(row['AveragePageviews']);
+    var bounceRate = parseFloat(row['BounceRate']);
+    var averageTimeOnSite = parseFloat(row['AverageTimeOnSite']);
+    //Logger.log("campaignId: " + campaignId);
+    //Logger.log("Ad AveragePageviews: " + averagePageviews);
     
-    adGroupMap[uniqueId].ads[adId].keywords[keywordId].keywordId = keywordId;
-    adGroupMap[uniqueId].ads[adId].keywords[keywordId].clicks = row['Clicks'];
-    adGroupMap[uniqueId].ads[adId].keywords[keywordId].impressions = row['Impressions'];
-    adGroupMap[uniqueId].ads[adId].keywords[keywordId].ctr = row['Ctr'];
+    try {
+      accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].bounceRate = bounceRate;
+      accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].averagePageviews = averagePageviews;
+      accountMap.campaigns[campaignId].adGroups[adGroupId].ads[adId].averageTimeOnSite = averageTimeOnSite;
+    } catch (e) {
+      //Logger.log("can't add GA data to ad: " + e);
+    }
   }
-  Logger.log("Ad Group Map Done");
-  return(adGroupMap);
+  
+  Logger.log("Ad Map and Keyword Ad Map Done");
+  var maps = new Object();
+  maps.adMap = adMap;
+  maps.keywordAdMap = keywordAdMap;
+  maps.accountMap = accountMap;
+  maps.keywordAdMapByAG = keywordAdMapByAG;
+  return(maps);
 }
 
+
 function buildKeywordIdMap() {
   
   var keywordIdMap = new Array();
+  var adGroupMap = new Array();
   
   var report = AdWordsApp.report(
-    'SELECT Id, KeywordMatchType, Criteria, CreativeQualityScore, PostClickQualityScore, SearchPredictedCtr, QualityScore ' +
+    'SELECT Id, CampaignId, AdGroupId, KeywordMatchType, Criteria, BounceRate, AverageTimeOnSite, AveragePageviews, CreativeQualityScore, PostClickQualityScore, SearchPredictedCtr, QualityScore ' +
     'FROM   KEYWORDS_PERFORMANCE_REPORT '+
-    'WHERE Impressions > 0 ' +
+    'WHERE Impressions >= 0 ' +
     'DURING LAST_30_DAYS'
   );
   
   var rows = report.rows();
   while (rows.hasNext()) {
     var row = rows.next();
-    keywordId = row['Id'];
-    keywordText = row['Criteria'];
-    keywordMatchType = row['KeywordMatchType'];
+    var keywordId = row['Id'];
+    var keywordText = row['Criteria'];
+    var keywordMatchType = row['KeywordMatchType'];
+    var adGroupId = row['AdGroupId']
+    var postClickQualityScore = row['PostClickQualityScore'];
+    var searchPredictedCtr = row['SearchPredictedCtr'];
+    var creativeQualityScore = row['CreativeQualityScore'];
+    var bounceRate = parseFloat(row['BounceRate']);
+    var averageTimeOnSite = parseFloat(row['AverageTimeOnSite']);
+    var averagePageviews = parseInt(row['AveragePageviews']);
+    var uniqueId = row['CampaignId'] + "-" + adGroupId + "-" + keywordId; 
+    
+    //Logger.log("KW BounceRate: " + bounceRate);
+    if(!adGroupMap[adGroupId]) {
+      adGroupMap[adGroupId] = new Object();
+      adGroupMap[adGroupId].countOfPostClickQualityScoreBelowAverage = 0;
+      adGroupMap[adGroupId].countOfSearchPredictedCtrBelowAverage = 0;
+      adGroupMap[adGroupId].countOfCreativeQualityScoreBelowAverage = 0;
+      adGroupMap[adGroupId].countOfPostClickQualityScoreAverage = 0;
+      adGroupMap[adGroupId].countOfSearchPredictedCtrAverage = 0;
+      adGroupMap[adGroupId].countOfCreativeQualityScoreAverage = 0;
+      adGroupMap[adGroupId].countOfPostClickQualityScoreAboveAverage = 0;
+      adGroupMap[adGroupId].countOfSearchPredictedCtrAboveAverage = 0;
+      adGroupMap[adGroupId].countOfCreativeQualityScoreAboveAverage = 0;
+    }
+    if(!adGroupMap[adGroupId].keywords) {
+      adGroupMap[adGroupId].keywords = new Array();
+    }
+    if(!adGroupMap[adGroupId].keywords[keywordId]) {
+      adGroupMap[adGroupId].keywords[keywordId] = new Object();
+    }
+    
+    adGroupMap[adGroupId].keywords[keywordId].bounceRate = bounceRate;
+    adGroupMap[adGroupId].keywords[keywordId].averageTimeOnSite = averageTimeOnSite;
+    adGroupMap[adGroupId].keywords[keywordId].averagePageviews = averagePageviews;
+    
+    
+    if(postClickQualityScore.toLowerCase().indexOf("below") != -1) {
+      adGroupMap[adGroupId].countOfPostClickQualityScoreBelowAverage++;
+    } else if(postClickQualityScore.toLowerCase().indexOf("above") != -1) {
+      adGroupMap[adGroupId].countOfPostClickQualityScoreAboveAverage++;
+    } else {
+      adGroupMap[adGroupId].countOfPostClickQualityScoreAverage++;
+    }
+    
+    if(searchPredictedCtr.toLowerCase().indexOf("below") != -1) {
+      adGroupMap[adGroupId].countOfSearchPredictedCtrBelowAverage++;
+    } else if(searchPredictedCtr.toLowerCase().indexOf("above") != -1) {
+      adGroupMap[adGroupId].countOfSearchPredictedCtrAboveAverage++;
+    } else {
+      adGroupMap[adGroupId].countOfSearchPredictedCtrAverage++;
+    }
+    
+    if(creativeQualityScore.toLowerCase().indexOf("below") != -1) {
+      adGroupMap[adGroupId].countOfCreativeQualityScoreBelowAverage++;
+    } else if(creativeQualityScore.toLowerCase().indexOf("above") != -1) {
+      adGroupMap[adGroupId].countOfCreativeQualityScoreAboveAverage++;
+    } else {
+      adGroupMap[adGroupId].countOfCreativeQualityScoreAverage++;
+    }
     
     if(!keywordIdMap[keywordId]) {
       keywordIdMap[keywordId] = new Object();
       keywordIdMap[keywordId].keywordText = keywordText;
       keywordIdMap[keywordId].keywordMatchType = keywordMatchType;
       keywordIdMap[keywordId].qualityScore = row['QualityScore'];
-      keywordIdMap[keywordId].postClickQualityScore = row['PostClickQualityScore'];
-      keywordIdMap[keywordId].searchPredictedCtr = row['SearchPredictedCtr'];
-      keywordIdMap[keywordId].creativeQualityScore = row['CreativeQualityScore'];
+      keywordIdMap[keywordId].postClickQualityScore = postClickQualityScore;
+      keywordIdMap[keywordId].searchPredictedCtr = searchPredictedCtr;
+      keywordIdMap[keywordId].creativeQualityScore = creativeQualityScore;
       //Logger.log("keywordId: " + keywordId + " keywordText: " + keywordText + " keywordMatchType: " + keywordMatchType);
     }
   }
+  var maps = new Object();
+  maps.keywordIdMap = keywordIdMap;
+  maps.adGroupMap = adGroupMap;
   Logger.log("KW ID Map Done");
-  return keywordIdMap;
+  return maps;
 }
 
-
+/*
+  // function setUpReportInGoogleSheets(spreadsheetUrl, spreadsheetName, accountManagers, overWriteOldData, sheetNames)
+  //---------------------------------------
+  // handles all the details of setting up the Google Spreadsheet to receive the report data
+  //
+  // output is an object
+  // destinationSpreadsheet.overwrite
+  // destinationSpreadsheet.isNew
+  // destinationSpreadsheet.spreadsheet (the Google spreadsheet object)
+  // destinationSpreadsheet.url
+  */
   function setUpReportInGoogleSheets(spreadsheetUrl, spreadsheetName, accountManagers, overWriteOldData, sheetNames) {
     
     var destinationSpreadsheet = new Object();
  1. 1
  2. 2
HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.