Showing posts with label regular expression. Show all posts
Showing posts with label regular expression. Show all posts

Monday, March 4, 2013

Fixing Capitalization Errors in Your Ads

One of the issues that marketers face when they have systems for automatically building creatives from feeds is quality control. I recently ran into an issue where I created around 1,000 new ads where the city name was IN ALL CAPS. Google of course doesn't like that much and I didn't like the idea of having to manually update 1,000 ads, so I put together the following script.

The script runs through your account for all of the disapproved ads and tries to find ones with words in ALL CAPS. I'm not sure what Google's limit on caps is, but in the script below, it looks for anything with 3 or more capital letters in a row. Then it replaces them, creates a new ad, and if it was successful, deletes the old ad.

I ran into some trouble trying to identify the reasons the ads were disapproved. It is not yet available in the API, but it has been requested. The other issue was that sometimes, the new ad you create will fail, which will cause you to delete the old one and not create a new one. I solved that one by counting the ads in the adgroup before and after I created the new ad in order to make sure my ad had been created. Again, I posted the feature request in the adwords scripting forums.


// Created By: Russ Savage
function main() {
  var find_caps = /[A-Z]{3,}/g;
  var SEP = '~~@~~'; // this needs to be something you would never put in your ads.
  var ad_iter ="ApprovalStatus = 'DISAPPROVED'").get();
  while(ad_iter.hasNext()) {
    var ad =;
    var old_ad_cnt = get_ad_count(ad.getAdGroup());
    var old_ad_str = [ad.getHeadline(),ad.getDescription1(),ad.getDescription2(),ad.getDisplayUrl()].join(SEP);
    var new_ad_str = old_ad_str;
    var m = "";
    while((m = find_caps.exec(new_ad_str)) != null) {
      new_ad_str = replace_all(new_ad_str,m[0],init_cap(m[0]),false);
    if(old_ad_str != new_ad_str) {
      var [new_headline,new_desc1,new_desc2,new_disp_url] = new_ad_str.split(SEP);
      ad.getAdGroup().createTextAd(new_headline, new_desc1, new_desc2, new_disp_url, ad.getDestinationUrl());
      var new_ad_cnt = get_ad_count(ad.getAdGroup());
      if(new_ad_cnt == (old_ad_cnt+1)) {
    } else {
      Logger.log("Skipping because no changes were made."); 
  function init_cap(s) {
    return s.charAt(0).toUpperCase() + s.slice(1).toLowerCase();
  // This function was adapted from: 
  function replace_all(original,str1, str2, ignore) {
    return original.replace(new RegExp(str1.replace(/([\/\,\!\\\^\$\{\}\[\]\(\)\.\*\+\?\|\<\>\-\&])/g,"\\$&"),(ignore?"gi":"g")),(typeof(str2)=="string")?str2.replace(/\$/g,"$$$$"):str2);
  function get_ad_count(ad_group) {
    var ad_iter =;
    var new_ad_cnt = 0;
    while(ad_iter.hasNext()) {;
    return new_ad_cnt;