Friday, November 23, 2012

Automatically Pause Ads with Low CTR

Recently, Brad over at CertifiedKnowledge.com published some tips about testing at scale.  One of the most common testing techniques he mentions is to create a ton of ads and let Google optimize the rotation for you.  The problem with this technique is that the losers are rarely deleted.  Well, using the script below, you can find the worst performing ads in all your adgroups and pause it (if there is at least one other ad in the adgroup).

Thanks,
Russ


//-----------------------------------
// Pause Ads with Low CTR
// Created By: Russ Savage
// FreeAdWordsScripts.com
//-----------------------------------
function main() {
  // Let's start by getting all of the adGroups that are active
  var ag_iter = AdWordsApp.adGroups()
  .withCondition("Status = ENABLED")
  .get();

  // Then we will go through each one
  while (ag_iter.hasNext()) {
    var ag = ag_iter.next();
    var ad_iter = ag.ads()
      .withCondition("Status = ENABLED")
      .forDateRange("ALL_TIME")
      .orderBy("Ctr DESC")
      .get();
    var ad_array = new Array();
    while(ad_iter.hasNext()) {
      ad_array.push(ad_iter.next());
    }
    if(ad_array.length > 1) {
      for(var i = 1; i < ad_array.length; i++) {
        ad_array[i].pause(); //or .remove(); to delete them 
      }
    }
  }
}

10 comments:

  1. would this be ads with impressions?

    ReplyDelete
  2. Great help. Thank you Russell

    Could you please help me to apply this condition (pausing ads with low CTR) in certain campaigns?

    I'm following naming convention for campaigns to differentiate "Search" and "Display" network. A "Search" campaign name will contain a string "SR" and "Display campaign name will contain a string "DP".

    I would like to apply the above script condition only for "Search" (SR) campaign's Ad Groups. Thanks in Advance.

    Thanks,
    Ren

    ReplyDelete
    Replies
    1. Hi Renjith, In order to do that, all you need to do is add an additional .withCondition() to the selector on lines 8 - 10.

      var ag_iter = AdWordsApp.adGroups()
      .withCondition("Status = ENABLED")
      .withCondition("CampaignName CONTAINS 'SR'")
      .get();

      You can use CONTAINS or CONTAINS_IGNORE_CASE. More info can be found here: AdGroupSelector withCondition().

      Thanks,
      Russ

      Delete
  3. Thank you very much Russel. Your guidance is a great help for many individuals like me.

    Thanks,
    Ren

    ReplyDelete
  4. Hi Russell,

    Thank you for your help, we have used several of your scripts and they have been very helpful.

    I was curious, is there a way to use this script to only pause one ad? It looks like this script pauses all of the ads in the adgroup besides the highest performing one.

    Thank you! :)

    ReplyDelete
    Replies
    1. Hi Becca, Pausing just one ad is easy enough. I am assuming you only want to pause the lowest performing ad in the adgroup.

      First, you want to make sure the ads are returned so that the first result is the worst performer. So on line 18, you want to change DESC to ASC (for ascending). You could also put a .limit(1) on there as well since you only care about 1 result.

      Next, you can replace lines 20 - 28 with this much more simple logic:

      if(ad_iter.hasNext()) {
      ad_iter.next().pause();
      }

      That should do it. Thanks for reading and please let me know if you have any other questions.

      ~Russ

      Delete
    2. Instead of .limit(1), it should be .withLimit(1).

      Delete
  5. Hi Russell,

    This is exactly what i'm looking for!

    I too just need to pause the lowest performing ad in terms of CTR for each ad group in the account.

    I've done the following:

    function main() {
    // Let's start by getting all of the adGroups that are active
    var ag_iter = AdWordsApp.adGroups()
    .withCondition("Status = ENABLED")
    .get();

    // Then we will go through each one
    while (ag_iter.hasNext()) {
    var ag = ag_iter.next();
    var ad_iter = ag.ads()
    .withCondition("Status = ENABLED")
    .forDateRange("ALL_TIME")
    .orderBy("Ctr ASC")
    .limit(1)
    .get();
    if(ad_iter.hasNext()) {
    ad_iter.next().pause();
    }
    }
    }

    However, I'm getting the following error 'TypeError: Cannot find function limit in object [AdSelector]. (line 15)'

    I'm not clued up at all on this so any help would be much appreciated.

    Thanks,

    Matt

    ReplyDelete
    Replies
    1. Hi Matt, My apologies. Instead of .limit(1), it should be .withLimit(1).

      Thanks,
      Russ

      Delete
    2. Thanks a lot Russ - that's worked a treat!

      Great blog - saved me a lot of time spent on manual tasks and problem solving.

      Cheers,

      Matt

      Delete