Destination URL Link Checker with AdWords Scripts

3,108 views
Skip to first unread message

Katie Croteau

unread,
May 20, 2013, 9:03:09 AM5/20/13
to adwords...@googlegroups.com
Hi,

I've been trying to create a script that would not only check my Destination URLs  for error, but to import all Keywords, Ad Groups, and Campaigns into a Google Spreadsheet daily so I know which URLs I need to switch out.  Here is where it gets a little complicated: my invalid URLs do not have a 404 error, but a simple text appears on the page that says 'not available'.  I feel like I've written my script over and over without success.  Can you take a look and help me identify where the errors are?

Thanks!
Katie

function main() {
  var keywordsIterator = AdWordsApp.keywords()
      .orderBy("Impressions DESC")
      .forDateRange("YESTERDAY")
      .withCondition(“Status = ENABLED”)
      .get();
  while (keywordsIterator.hasNext()) {
      var keyword = keywordsIterator.next ();
      var urlToTest = keywords.getDestinationURL();
      var responseText = response.getContentText ().withCondition(“Text CONTAINS_IGNORE_CASE ‘not available’”); 
  var now = new Date();
  var reportName = "DestinationURLDailyReport-" + Utilities.formatDate(now, "EST", "yyyyMMdd");
  var spreadsheet = SpreadsheetApp.create(reportName);
  var sheet = spreadsheet.getActiveSheet();
  sheet.getRange("A1").setValue("Keyword");
  sheet.getRange("B1").setValue("Campaign");
  sheet.getRange("C1").setValue("AdGroup");
  sheet.getRange("D1").setValue("Impressions");
  sheet.getRange("E1").setValue("DestinationURL");

  for (var row = 2; keywordsIterator.hasNext(); row ++) {
    var keyword = keywordsIterator.next();
    var stats = keyword.getStatsFor("YESTERDAY");

    sheet.getRange("A" + row).setValue(keyword.getText());
    sheet.getRange("B" + row).setValue(keyword.getCampaign());
    sheet.getRange("C" + row).setValue(stats.getAdGroup());
    sheet.getRange("D" + row).setValue(stats.getImpressions());
    sheet.getRange("E" + row).setValue(stats.getDestinationURL());
  }

  Logger.log("Report ready! Visit the following URL to see it:");
  Logger.log("https://docs.google.com/spreadsheet/ccc?key=" + spreadsheet.getId());
}

Kevin Winter (AdWords Scripts Team)

unread,
May 20, 2013, 2:38:18 PM5/20/13
to adwords...@googlegroups.com
Hi Katie,
  The destination URL of the keyword/ad is actually just a string.  You'll need to do something like this to test the URL to make sure it is valid:

function isValid(url) {
 
try {
   
var response = UrlFetchApp.fetch(url, { muteHttpExceptions: true} );
   
if (response.getResponseCode() < 300 && response.getContentText().indexOf('not available') == -1) {
     
return true;
   
}
 
} catch (e) {
   
// Invalid URl.
 
}
 
return false;
}

pass urlToTest to this function and if false, consider it invalid.

- Kevin Winter
AdWords Scripts Team

Katie Croteau

unread,
May 20, 2013, 4:16:11 PM5/20/13
to adwords...@googlegroups.com
Thank you so much for the help!  Unfortunately, I'm still receiving an error message 'invalid character'.  Any ideas?

function main() 
{var keywordsIterator = AdWordsApp.keywords()
      .orderBy("Impressions DESC")
      .forDateRange("YESTERDAY")
      .withCondition(“Status = ENABLED”)
      .get();
}
function isValid(url) {
  try {
    var response = UrlFetchApp.fetch(url, { muteHttpExceptions: true} );
    if (response.getResponseCode() < 300 && response.getContentText().indexOf('not available') == -1) {
      return true;
    }
  } catch (e) {
    // Invalid URl.
  }
  return false;
}
  var now = new Date();
  var reportName = "DestinationURLDailyReport-" + Utilities.formatDate(now, "EST", "yyyyMMdd");
  var spreadsheet = SpreadsheetApp.create(reportName);
  var sheet = spreadsheet.getActiveSheet();
  sheet.getRange("A1").setValue("Keyword");
  sheet.getRange("B1").setValue("Campaign");
  sheet.getRange("C1").setValue("AdGroup");
  sheet.getRange("D1").setValue("Impressions");
  sheet.getRange("E1").setValue("DestinationURL");

  for (var row = 2; keywordsIterator.hasNext(); row ++) {
    var keyword = keywordsIterator.next();
    var stats = keyword.getStatsFor("YESTERDAY");

    sheet.getRange("A" + row).setValue(keyword.getText());
    sheet.getRange("B" + row).setValue(keyword.getCampaign());
    sheet.getRange("C" + row).setValue(stats.getAdGroup());
    sheet.getRange("D" + row).setValue(stats.getImpressions());
    sheet.getRange("E" + row).setValue(stats.getDestinationURL());
  }

{Logger.log("Report ready! Visit the following URL to see it:");
  Logger.log("https://docs.google.com/spreadsheet/ccc?key=" + spreadsheet.getId());
}
On Monday, May 20, 2013 9:03:09 AM UTC-4, Katie Croteau wrote:

Kevin Winter (AdWords Scripts Team)

unread,
May 21, 2013, 5:31:00 PM5/21/13
to adwords...@googlegroups.com
Hi Katie,
  There were a bunch of bugs in your script.  The illegal character comes from the "smart quotes" character in your withCondition(Stats) line.  A working version of your script is below.  You might want to look into following some javascript tutorials on a site like codecademy.com.

function main() {
 
var keywordsIterator = AdWordsApp.keywords()
     
.orderBy("Impressions DESC")
     
.forDateRange("YESTERDAY")
     
.withCondition("Status = ENABLED")
     
.get();

 
var now = new Date();
 
var reportName = "DestinationURLDailyReport-" + Utilities.formatDate(now, "EST", "yyyyMMdd");
 
var spreadsheet = SpreadsheetApp.create(reportName);
 
var sheet = spreadsheet.getActiveSheet();
  sheet
.getRange("A1").setValue("Keyword");
  sheet
.getRange("B1").setValue("Campaign");
  sheet
.getRange("C1").setValue("AdGroup");
  sheet
.getRange("D1").setValue("Impressions");
  sheet
.getRange("E1").setValue("DestinationURL");


 
for (var row = 2; keywordsIterator.hasNext(); row ++) {
   
var keyword = keywordsIterator.next();
   
var stats = keyword.getStatsFor("YESTERDAY");


    sheet
.getRange("A" + row).setValue(keyword.getText());

    sheet
.getRange("B" + row).setValue(keyword.getCampaign().getName());
    sheet
.getRange("C" + row).setValue(keyword.getAdGroup().getName());
    sheet
.getRange("D" + row).setValue(stats.getImpressions());
    sheet
.getRange("E" + row).setValue(keyword.getDestinationUrl());

 
}


 
Logger.log("Report ready! Visit the following URL to see it:");
 
Logger.log("https://docs.google.com/spreadsheet/ccc?key=" + spreadsheet.getId());
}


function isValid(url) {
 
try {
   
var response = UrlFetchApp.fetch(url, { muteHttpExceptions: true} );
   
if (response.getResponseCode() < 300 && response.getContentText().indexOf('not available') == -1) {
     
return true;
   
}
 
} catch (e) {
   
// Invalid URl.
 
}
 
return false;
}

- Kevin Winter
AdWords Scripts Team

Oleg Amirdzhanov

unread,
Jun 18, 2013, 4:09:21 PM6/18/13
to adwords...@googlegroups.com

Hi Kevin.  I have been using AdWords script for an identical reason for a few months now.  The problem is tha once you introduce the piece of code (close equivalent of the try-catch function in the example, that fetches page's content and checks for target message, execution time dramatically increases, and only 10000 keywords get checked after which script expires.  Is there a better way of implementation that might save time and reduce iteration?  Thank you!

_oleg

Kevin Winter (AdWords Scripts Team)

unread,
Jun 19, 2013, 2:34:24 PM6/19/13
to adwords...@googlegroups.com
Hi Oleg,
  Unfortunately, there's not much you can do to speed up thousands of URL fetches.  You might want to try to alter the script such that it processes urls in chunks and picks up where it leaves off.  That way you can schedule it to run hourly and eventually complete a workload too large for a single execution.

If you just wanted all the URLs to be periodically checked, you could possibly add a label to each keyword you've checked and make your selector only select keywords that don't have this label.  Then, when you've checked all URLs, remove the label from everything that has it.

- Kevin Winter
AdWords Scripts Team

Ernő Horváth

unread,
Jun 20, 2013, 3:41:53 AM6/20/13
to adwords...@googlegroups.com
Hi Oleg,

Alternatively you can use this script it does the same that you need:

Or you can modify your script not to check every single url every time just the ones it hasn't checked before.
Because if you use the same landing page 100 times that means 99 checks are useless.

Regards,
Erno Horvath 

Russell Savage

unread,
Jun 20, 2013, 11:18:03 AM6/20/13
to adwords...@googlegroups.com
Hi Guys, I'm the owner of FreeAdWordsScripts.com. Please let me know if you have any problems using the scripts from my site and I'll try my best to help you out.

Thanks,
Russ
Message has been deleted

Vikrant Pathania

unread,
Jun 26, 2013, 2:09:12 PM6/26/13
to adwords...@googlegroups.com
Hi Russ,

I saw your script for checking broken urls.  How would one modify your script to actually pause those keywords associated with destination urls going to a 404 error page?  This 404 error redirects to our homepage and are wasted spend.  

Marlon Haniff

unread,
Feb 19, 2015, 8:11:39 AM2/19/15
to adwords...@googlegroups.com
My situation is a bit different.  I've set up in my htaccess file to redirect all 404 pages to a specific URL:  foo.com/404page.  Is there a script that detects a specific URL page for an active ad and report it back to me via email?  

I could easily redirect borked pages to my home page but I would be wasting money since my home page is not designed to be a landing page.

Alexander Wang

unread,
Feb 19, 2015, 3:39:58 PM2/19/15
to adwords...@googlegroups.com
Hi Marlon,

Someone recently asked about updating the link checker solution so that it also made note of URLs that led to "Out of stock" product pages. You should be able to adjust their solution so that it checks if the page is your specific 404 page.

Instead of looking for "There are no results that match", use a string that identifies the 404 page. This could be some visible message on the page or some html tag or something. Instead of returning "Out of stock" in this case, you could return 404. That way the "getUrlStatus(url)" method will:
1. Fetch the page.
2. If it successfully made the request, check the response for the 404 text.
3. Return 404 if it found the text.
4. Return the response's response code otherwise.

Cheers,
Alex

Jason-Rakuten

unread,
Dec 23, 2015, 5:07:58 PM12/23/15
to AdWords Scripts Forum
Does anyone know how to do a script that pauses ads with Dest landing pages with "out of stock" and then re-activate ads that have switched back from OOS to instock? I feel like all of the script solutions that I have seen are great at pausing ads that are OOS, but then they don't check the reverse, Additionally, they typically ignore ads that are already paused. Would love to hear solutions for product pages that shuffle from in stock to out of stock frequently.
Reply all
Reply to author
Forward
0 new messages