SHARE
TWEET

Untitled

a guest Feb 22nd, 2019 251 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // REMOVE UNDERPERFORMING TEXT ADS
  2. // -------------------------------------------------
  3. // Script created by Frederick Vallaeys
  4. // Optmyzr - http://www.optmyzr.com
  5. // Copyright 2012-2013 - Optmyzr
  6. //
  7. // WARNING: Test all scripts in preview mode before running them!
  8. // This script can make changes to your account. There is no 'undo'
  9. // feature so make a backup of your account in AdWords Editor before
  10. // running this script.
  11.  
  12. function main() {
  13.  
  14.   // SETTINGS - Change these if needed
  15.   var time = "LAST_30_DAYS"; //TODAY, YESTERDAY, LAST_7_DAYS, THIS_WEEK_SUN_TODAY, LAST_WEEK, LAST_14_DAYS, LAST_30_DAYS, LAST_BUSINESS_WEEK, LAST_WEEK_SUN_SAT, THIS_MONTH, LAST_MONTH, ALL_TIME
  16.   var campaignSelectorStatement = "Name CONTAINS_IGNORE_CASE ''"
  17.   var minAdsToKeepPerAdGroup = 2;
  18.   var suggestMode = 1;
  19.   var deleteAds = 0;
  20.   var pauseAds = 1;
  21.   // END SETTINGS
  22.  
  23.   // Script variables
  24.   var minImpressionsBeforeAdCanBeDeleted = 25;
  25.   var minImpressionsForAdGroupBeforeOptimization = 100;
  26.   var percentImpressionVariationAllowedBeforeDeleting = .1;
  27.   var percentCTRVariationAllowedBeforeDeleting = .1;
  28.   var percentConversionVariationAllowedBeforeDeleting = .1;
  29.  
  30.   Logger.log("Remove Underperforming Ads");
  31.   Logger.log("-------------------------------");
  32.   Logger.log("This script's copyright belongs to Optmyzr and Frederick Vallaeys. The code may not be copied, modified or distributed without permission.")
  33.   Logger.log("");
  34.   Logger.log("Purpose");
  35.   Logger.log("-------");
  36.   Logger.log("This script helps you identify and remove underperforming text ads in your AdWords account.");
  37.   Logger.log("");
  38.   Logger.log("Settings:");
  39.   Logger.log("--------");
  40.   Logger.log("- date range: " + time);
  41.   Logger.log("- evaluate all campaigns that match the selector '" + campaignSelectorStatement + "'");
  42.   Logger.log("- keep at least " + minAdsToKeepPerAdGroup + " ad variations in each ad group");
  43.   Logger.log("- evaluate only ad groups with at least " + minImpressionsForAdGroupBeforeOptimization + " impressions");
  44.   Logger.log("- do not remove ads with fewer than " + minImpressionsBeforeAdCanBeDeleted + " impressions");
  45.   Logger.log("- remove ads that underdeliver impressions by more than " + percentImpressionVariationAllowedBeforeDeleting*100 + "%");
  46.   Logger.log("- save underperforming ads if their CTR outperforms their impressions by at least " + percentCTRVariationAllowedBeforeDeleting*100 + "%");
  47.   Logger.log("- save underperforming ads if their conversions outperform their impressions by at least " + percentConversionVariationAllowedBeforeDeleting*100 + "%");
  48.   Logger.log("- test mode: " + suggestMode);
  49.   Logger.log("- delete ads: "+ deleteAds);
  50.   Logger.log("- pause ads: " + pauseAds);
  51.   Logger.log("");
  52.   Logger.log("");
  53.  
  54.  
  55.  
  56.  
  57.  
  58.   // Get an iterator over campaigns so we can total all the impressions
  59.   var campaignIterator = AdWordsApp.campaigns()
  60.       .forDateRange(time)
  61.       .withCondition("Status = ENABLED")
  62.       .withCondition(campaignSelectorStatement)
  63.       .orderBy("Impressions DESC")
  64.       .withLimit(10)
  65.       .get();
  66.  
  67.   var adArray = new Array();
  68.   var deletionAllowed = 1;
  69.  
  70.   var totalCostSaved = 0;
  71.   var totalClicksGained = 0;
  72.  
  73.   while(campaignIterator.hasNext()) {
  74.     var campaign = campaignIterator.next();
  75.     var campaignName = campaign.getName();
  76.     Logger.log("Campaign: " + campaignName);
  77.  
  78.     var campaignAdGroupIterator = campaign.adGroups()
  79.         .forDateRange(time)
  80.         .withCondition("Status = ENABLED")
  81.         .withCondition("Impressions >= " + minImpressionsForAdGroupBeforeOptimization)
  82.         .orderBy("Impressions DESC")
  83.         .get();
  84.    
  85.     while(campaignAdGroupIterator.hasNext()) {
  86.       var adGroup = campaignAdGroupIterator.next();
  87.       var adGroupName = adGroup.getName();
  88.       var adGroupStats = adGroup.getStatsFor(time);
  89.       var adGroupImpressions = adGroupStats.getImpressions();
  90.       var adGroupClicks = adGroupStats.getClicks();
  91.       var adGroupConversions = adGroupStats.getConversions();
  92.       var adGroupCtr = adGroupStats.getCtr();
  93.       var adGroupConversionRate = adGroupStats.getConversionRate();
  94.       var adGroupAvgCpc = adGroupStats.getAverageCpc();
  95.       var adGroupAdIterator = adGroup.ads()
  96.           .withCondition("Status = ENABLED")
  97.           .forDateRange(time)
  98.           .orderBy("Impressions DESC")
  99.           .get();
  100.       Logger.log("  Ad Group Name: " + adGroupName);
  101.       Logger.log("    impressions: " + adGroupImpressions);
  102.       var textAdImpressions = 0;
  103.       var textAdClicks = 0;
  104.       var textAdConversions = 0;
  105.       var textAdCount = 0;
  106.       var templateAdImpressions = 0;
  107.      
  108.       while (adGroupAdIterator.hasNext()) {
  109.    
  110.         var ad = adGroupAdIterator.next();
  111.         var adHeadline = ad.getHeadline();
  112.         var adLine1 = ad.getDescription1();
  113.         var adLine2 = ad.getDescription2();
  114.         var destinationUrl = ad.getDestinationUrl();
  115.         var displayUrl = ad.getDisplayUrl();
  116.         var adType = ad.getType();
  117.         var adStats = ad.getStatsFor(time);
  118.         var adImpressions = adStats.getImpressions();
  119.         var adClicks = adStats.getClicks();
  120.         var adAvgCpc = adStats.getAverageCpc();
  121.         var adConversions = adStats.getConversions();
  122.         if(adType == "TEXT_AD") {
  123.           textAdImpressions+= adImpressions;
  124.           textAdClicks += adClicks;
  125.           textAdConversions += adConversions;
  126.           textAdCount++;
  127.           adArray.push(new adUnit(campaignName, adGroupName, adType, adHeadline, adLine1, adLine2, displayUrl, destinationUrl, adImpressions, adClicks, adConversions, adAvgCpc, adGroupCtr, adGroupConversionRate, adGroupAvgCpc));
  128.         }
  129.         if(adType == "TEMPLATE_AD") {
  130.           templateAdImpressions+= adImpressions;
  131.         }
  132.       }
  133.       Logger.log("    contains " + textAdCount + " text ads");
  134.       Logger.log("");
  135.      
  136.       if(textAdCount > minAdsToKeepPerAdGroup && adGroupImpressions >= minImpressionsForAdGroupBeforeOptimization)
  137.       {
  138.         // Sort the ads by impressions from high to low
  139.         adArray.sort(function(a,b) {
  140.           return a.impressions-b.impressions
  141.         });
  142.        
  143.         var deletionCount = 0;
  144.      
  145.         // Process the ad group's ads now that we have all the stats
  146.         for (var i = 0; i < adArray.length; i++) {
  147.           var ad = adArray[i];
  148.           var headline = ad.headline;
  149.           var line1 = ad.line1;
  150.           var line2 = ad.line2;
  151.           var displayUrl = ad.displayUrl;
  152.           var destinationUrl = ad.destinationUrl;
  153.           var campaignName = ad.campaignName;
  154.           var adGroupName = ad.adGroupName;
  155.           var impressions = ad.impressions;
  156.           var clicks = ad.clicks;
  157.           var ctr = 100 * clicks/impressions;
  158.           var cpc = ad.cpc;
  159.           var conversions = ad.conversions;
  160.           var type = ad.type;
  161.           var adGroupCtr = 100 * ad.adGroupCtr;
  162.           var adGroupConversionRate = ad.adGroupConversionRate;
  163.           var adGroupAvgCpc = ad.adGroupAvgCpc;
  164.          
  165.           var minImpPercent = (100 / textAdCount) * (1-percentImpressionVariationAllowedBeforeDeleting);
  166.        
  167.           if(type == "TEXT_AD") {
  168.             var percentImpressions = impressions / textAdImpressions * 100;
  169.             var percentClicks = clicks / textAdClicks * 100;
  170.             var percentConversions = conversions / textAdConversions * 100;
  171.             Logger.log("      | " + headline);
  172.             Logger.log("      | " + line1);
  173.             Logger.log("      | " + line2);
  174.             Logger.log("      | " + displayUrl);
  175.             Logger.log("       ----------------------------------------------");
  176.             Logger.log("       imp:" + percentImpressions.toFixed(2) + "% | clicks: " + percentClicks.toFixed(2) + "% | conv: " + percentConversions.toFixed(2) + "%");
  177.             var relativeConversions = (1 - percentConversionVariationAllowedBeforeDeleting) * percentConversions;
  178.             var relativeCTR = (1 - percentCTRVariationAllowedBeforeDeleting) * percentClicks;
  179.             if(deletionAllowed) {
  180.               if(percentImpressions < minImpPercent)
  181.               {
  182.                 if(textAdConversions > 0)
  183.                 {
  184.                   if(relativeConversions > percentImpressions) {
  185.                     Logger.log("  <-- saved by conversions");
  186.                   } else {
  187.                     deleteAd(campaignName, adGroupName, headline, line1, line2, displayUrl, destinationUrl, suggestMode, pauseAds, deleteAds);
  188.                     deletionCount++;
  189.                    
  190.                     var clicksGained = (adGroupCtr - ctr) / 100 * impressions;
  191.                     totalClicksGained += clicksGained;
  192.                     var costSaved = (cpc - adGroupAvgCpc) * clicks;
  193.                     totalCostSaved += costSaved;
  194.                     if(clicksGained > 0) {
  195.                       Logger.log("Removing this ad may get you " + clicksGained.toFixed(0) + " additional clicks over 30 days.");
  196.                     }
  197.                     if(costSaved > 0) {
  198.                       Logger.log("Removing this ad may save you $" + costSaved.toFixed(2) + " over 30 days.");
  199.                     }
  200.                   }
  201.                 } else {
  202.                   if(relativeCTR > percentImpressions) {
  203.                     Logger.log("  <-- saved by CTR");
  204.                   } else {
  205.                     deleteAd(campaignName, adGroupName, headline, line1, line2, displayUrl, destinationUrl, suggestMode, pauseAds, deleteAds);
  206.                     deletionCount++;
  207.                    
  208.                     var clicksGained = (adGroupCtr - ctr) / 100 * impressions;
  209.                     totalClicksGained += clicksGained;
  210.                     var costSaved = (cpc - adGroupAvgCpc) * clicks;
  211.                     totalCostSaved += costSaved;
  212.                     if(clicksGained > 0) {
  213.                       Logger.log("Removing this ad may get you " + clicksGained.toFixed(0) + " additional clicks over 30 days.");
  214.                     }
  215.                     if(costSaved > 0) {
  216.                       Logger.log("Removing this ad may save you $" + costSaved.toFixed(2) + " over 30 days.");
  217.                     }
  218.                   }
  219.                 }
  220.               }
  221.             }
  222.           }
  223.           if(type == "TEMPLATE_AD") {
  224.             // Not in use because we can't see the ad sizes in the script so we can't compare apples to apples
  225.             //var percentImpressions = impressions / templateAdImpressions * 100;
  226.           }
  227.           Logger.log(" ");
  228.           if((textAdCount - deletionCount) <= minAdsToKeepPerAdGroup) {
  229.             //Logger.log("Deletion no longer allowed, min ad group size reached");
  230.             deletionAllowed = 0;
  231.           }
  232.         }
  233.       } else {
  234.         Logger.log("    The ad group above did not qualify for optimization - check your settings to change this");
  235.         Logger.log("");
  236.       }
  237.       var adArray = new Array();
  238.       var adStatsArray = new Array();
  239.       var textAdImpressions = 0;
  240.       var textAdClicks = 0;
  241.       var textAdConversions = 0;
  242.       var templateAdImpressions = 0;
  243.       var thisAGAdCount = 0;
  244.       var textAdCount = 0;
  245.       var deletionCount = 0;
  246.       var deletionAllowed = 1;
  247.     }
  248.   }
  249.  
  250.   Logger.log("This entire optimization may get you " + totalClicksGained.toFixed(0) + " additional clicks ");
  251.   Logger.log("and save you $" + totalCostSaved.toFixed(2) + " over 30 days.");
  252.  
  253. }
  254.  
  255. function adUnit(campaignName, adGroupName, type, headline, line1, line2, displayUrl, destinationUrl, impressions, clicks, conversions, cpc, adGroupCtr, adGroupConversionRate, adGroupAvgCpc)
  256.   {
  257.     this.campaignName = campaignName;
  258.     this.adGroupName = adGroupName;
  259.     this.type = type;
  260.     this.headline = headline;
  261.     this.line1 = line1;
  262.     this.line2 = line2;
  263.     this.displayUrl = displayUrl;
  264.     this.destinationUrl = destinationUrl;
  265.     this.impressions = impressions;
  266.     this.clicks = clicks;
  267.     this.conversions = conversions;
  268.     this.cpc = cpc;
  269.     this.adGroupCtr = adGroupCtr;
  270.     this.adGroupConversionRate = adGroupConversionRate;
  271.     this.adGroupAvgCpc = adGroupAvgCpc;
  272.   }
  273.  
  274. function deleteAd(campaignName, adGroupName, headline, line1, line2, displayUrl, destinationUrl, suggestMode, pauseAd, deleteAd)
  275. {
  276.   var adToProcessIterator = AdWordsApp.ads()
  277.   .withCondition("Headline = \"" + headline.replace(/[\[\]\"]/g, "") + "\"")
  278.   .withCondition("Description1 = \"" + line1.replace(/[\[\]\"]/g, "") + "\"")
  279.   .withCondition("Description2 = \"" + line2.replace(/[\[\]\"]/g, "") + "\"")
  280.   .withCondition("DisplayUrl = '" + displayUrl + "'")
  281.   .withCondition("DestinationUrl = '" + destinationUrl + "'")
  282.   .withCondition("AdGroupName = '" + adGroupName + "'")
  283.   .withCondition("CampaignName = '" + campaignName + "'")
  284.   .get();
  285.  
  286.   while(adToProcessIterator.hasNext())
  287.   {
  288.     var adToProcess = adToProcessIterator.next();
  289.     var headline = adToProcess.getHeadline();
  290.     var line1 = adToProcess.getDescription1();
  291.     var line2 = adToProcess.getDescription2();
  292.  
  293.    
  294.     if(pauseAd) {
  295.       if(!suggestMode) {
  296.         adToProcess.pause();
  297.         Logger.log("    >> Ad paused <<");
  298.       } else {
  299.         Logger.log("    >> Test mode: this ad would have been paused otherwise <<");
  300.       }
  301.     } else if(deleteAd) {
  302.       if(!suggestMode) {
  303.         adToProcess.remove();
  304.         Logger.log("    >> Ad deleted <<");
  305.       } else {
  306.         Logger.log("    >> Test mode: this ad would have been deleted otherwise <<");
  307.       }
  308.     }
  309.   }
  310. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top