Checking content website - Out of Stock

55 views
Skip to first unread message

Eldrid de Boer

unread,
Jun 15, 2023, 9:12:17 AM6/15/23
to Google Ads Scripts Forum
Hi all,

We are trying to implement a script to check if there are search ads online that refer to a product that is out of stock. But when I try to run the script I get the following message:

Has anybody had this message before or knows how to can fix it?
"TypeError: object.getDestinationUrl is not a function
at main (Code:101:22) at Object.<anonymous> (adsapp_compiled:19967:54)"

I used the following script (we don't want the ads to be automatically paused, that's why we used this script)


/**
*
* AdWords Script for checking the contents of landing pages.
* Goes to the final URL of keywords or ads, then searches the source code for
* user defined strings.
*
* Version: 1.0
* Google AdWords Script maintained by brainlabsdigital.com
*
**/

function main() {
 
  var messagesToCheckFor = ['<span class="soldout">'];
  // What out of stock messages appear on the source code of your landing pages?
  // Enter like ["Out of stock", "<em>0 available</em>"]
 
  var trimAtQuestionMark = true;
  // Do you want to remove all parameters which occur after the '?' character?
  // Enter true or false
 
  var type = "ads";
  // Choose "keywords" or "ads"
  // Are your final URLs at the keyword or ad level?
 
  var recipients = [];
  // If set, these addresses will be emailed with a list of any bad URLs.
  // Enter like ["a...@b.com"] or ["a...@b.com","c...@d.com","e...@g.co.uk"]
  // Leave as [] to skip.
 
 
  // Optional filtering options
  // Enter like ["hey", "jude"]
  // Leave as [] to skip
  var containsArray = [];
  // If set, only campaigns whose names contain these phrases will be checked
 
  var excludesArray = [];
  // If set, campaigns whose names contain any of these phrases will be ignored.
 
  var labelArray = [];
  // If set, only keywords / ads with these labels will be checked
  // Case sensitive.
 
 
  // Status options
  // Choose from ["ENABLED"] if you only want enabled entities
  // ["PAUSED"] if you only want paused entities
  // ["ENABLED","PAUSED"] if you want enabled and paused entities
  var campaignStatus = ["ENABLED"];
  // The status of the campaigns
 
  var adGroupStatus = ["ENABLED"];
  // The status of the ad groups
 
  var status = ["ENABLED"];
  // The status of the keywords / ads
 
 
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
  //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
 
 
 
  var urls = [];
  var bad_urls = [];
  var urlFetchOptions = {muteHttpExceptions: true};
  var countEntities = 0;
 
 
  var conditions = [];
  if (containsArray.length > 0) {
    conditions.push(" where the campaign name contains " + containsArray.join(", "));
  }
  if (excludesArray.length > 0) {
    conditions.push(" where the campaign name excludes " + excludesArray.join(", "));
  }
  if (labelArray.length > 0) {
    conditions.push(" where the " + type + " are labelled " + labelArray.join(", "));
  }    
 
  if (containsArray.length === 0) {
    containsArray.push("");
  }
 
  for(var i = 0; i < containsArray.length; i++){
    var string = iteratorConstructor(type, containsArray[i], excludesArray, labelArray, status, campaignStatus, adGroupStatus);
    eval(string);
    countEntities += iterator.totalNumEntities();
    excludesArray.push(containsArray[i]);
    while(iterator.hasNext()){
      var object = iterator.next();
      var url = object.urls().getFinalUrl();
     
      if(url == null || url == undefined){
        url = object.getDestinationUrl();
      }
     
      if(url !== null && url !== undefined){
        if(trimAtQuestionMark){
          url = url.split('?')[0];
        }
        if(urls.indexOf(url) === -1) {
          urls.push(url);
        }
      }
    }
  }
 
  if (countEntities == 0) {
    throw "No " + type + " found" + conditions.join("; and");
  }
  Logger.log(countEntities + " " + type + " found" + conditions.join("; and"));
  Logger.log(urls.length + " unique URLs to check.");
 
  for(var x in urls){
    var response = UrlFetchApp.fetch(urls[x],urlFetchOptions);
    var code = response.getContentText();
    for(var y = 0; y < messagesToCheckFor.length; y++){
      var message = messagesToCheckFor[y];
      if(code.indexOf(message) !== -1){
        bad_urls.push(urls[x]);
        break;
      }
    }
  }
 
  if (bad_urls.length === 0) {
    Logger.log("No bad URLs found.");
  } else {  
    Logger.log(bad_urls.length + " found:");
    Logger.log(bad_urls.join("\n"));
  }
 
  if(recipients.length > 0 && bad_urls.length > 0){
    var name = AdWordsApp.currentAccount().getName();
    var subject = name + " URL checking";
    var body = 'The following URLs were found to have one of the following phrases in their web page source code. \n\nPhrases:\n"' + messagesToCheckFor.join('",\n"') + '"\n\nURLs:\n';
    body += bad_urls.join("\n");
    MailApp.sendEmail(recipients.join(","),subject,body);
    Logger.log("Email sent to " + recipients.join(", "));
  }
 
  function iteratorConstructor(type, containsString, excludesArray, labelArray, status, campaignStatus, adGroupStatus){
   
    var string = "var iterator = AdWordsApp."+type+"()";
    if (containsString != "") {
      string = string + ".withCondition('CampaignName CONTAINS_IGNORE_CASE " + '"' + containsString + '"' + "')";
    }
    for(var i = 0; i < excludesArray.length; i++){
      string = string + ".withCondition('CampaignName DOES_NOT_CONTAIN_IGNORE_CASE " + '"' + excludesArray[i] + '"' + "')";
    }
    if(labelArray.length > 0){
      string = string + ".withCondition('LabelNames CONTAINS_ANY " + '["' + labelArray.join('","') + '"]' + "')";
    }
   
    string = string + ".withCondition('Status IN [" + status.join(",") + "]')";
    string = string + ".withCondition('CampaignStatus IN [" + campaignStatus.join(",") + "]')";
    string = string + ".withCondition('AdGroupStatus IN [" + adGroupStatus.join(",") + "]')";
    string = string + ".orderBy('Cost DESC').forDateRange('LAST_30_DAYS')";
    string = string + ".withLimit(50000)";
   
    string = string + ".get();"
   
    return string;
   
  }
 
}

Nils Rooijmans

unread,
Jun 16, 2023, 9:25:27 AM6/16/23
to Google Ads Scripts Forum
the 'getDestinationUrl()'  method has been deprecated and should ne replaced with  the 'getFinalUrl()' method to get the URLs. 
Instead of ad. getDestinationUrl(), try ad.urls().getFinalUrl().


Hope this helps,

Nils Rooijmans
https://nilsrooijmans.com
See my Google Ads Scripts FAQ to avoid the same mistakes I made: https://nilsrooijmans.com/google-ads-scripts-faq/



Google Ads Scripts Forum Advisor

unread,
Jun 20, 2023, 6:41:21 AM6/20/23
to adwords...@googlegroups.com

Hi,

Thanks for reaching out to Google Ads Scripts Support.

@Nils Rooijmans 
Thank you for providing your insights about this concern.

You may proceed with Nils suggestion in implementing the .getDestinationUrl() as this method is deprecated. As per this help center articleFinal URLs are replacing destination URLs as part of the URL upgrade. You can no longer create or edit ads that use a destination URL. We would recommend you use these methods, or getFinalUrl instead.

Additionally, please note that the legacy version is deprecated, and scripts still conforming to the said version will not perform as expected. Kindly note that, currently, Google Ads Scripts' reporting infrastructure is backed by the Google Ads API and uses the Google Ads Query Language. With this, we would recommend you migrate the script to the new script experience version to ensure continued functionality. You may use our Migration documentation for more information about the new script experience.

Links included in this email:

 
This message is in relation to case "ref:_00D1U1174p._5004Q2mUY6k:ref"

Thanks,
 
Google Logo Google Ads Scripts Team


Reply all
Reply to author
Forward
0 new messages