Advertisement
Guest User

Untitled

a guest
Feb 22nd, 2019
311
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 13.46 KB | None | 0 0
  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. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement