Google Ads Script – “Past Violations” Alert

Google continues to surprise me.

Today was the first time I encountered an ad that was disapproved for “Past violations”.

Here’s how Google describes these:


Google continuously re-reviews ads to ensure they conform with our policies. During the standard re-review process, our system may identify disapproved ads that no longer violate our policies. If your ad was disapproved for an extended period of time and our enforcement system later decides that the policy no longer applies, we may keep the ad disapproved and classify the ad as “Past Violation”.  We do this to prevent you from unintentionally exhausting spend on old ads. 

Fan-freaking-tastic. Google acknowledges that the ad had been disapproved for no legit reason in the past, and now still doesn’t show my ad.
Also, I did not see an alert or notification of any kind for this type of disapproval…

Here’s the thing:
Unless you check for these kinds of disapprovals yourself and take action, these ads will get zero impressions.

How to fix?

Appeal policy decisions from an ad’s “Status” column:

1. In the “Status” column of the ad you want to start serving, hover over the ad status, and click Appeal.
2. Under “Reason for appealing,” select Made changes to comply with the policy.
3. Under “Appeal the following,” select which ads you want to appeal.
4. Click Submit.

More details:
https://support.google.com/adspolicy/answer/10658384?hl=en

Since I am not a fan of manually checking for “Past violations” every day, I’ve created a script to alert us on any “Past violations“.

➥  ACTION: For the next ten minutes, mute slack and your phone and install the script.

(Don’t worry if you have never run a script before. You do not need any coding skills. It is as simple as copy-paste.)

 

INSTRUCTIONS:

  1. See the script code below. Install the script in your account.
    Don’t worry if you have never done this before. You do not need any coding skills. It is as simple as copy-paste. Simply follow these instructions on how to set up and schedule Google Ads scripts.
  2. Create a new Google Sheet
    (tip for Chrome users: simply type ‘sheets.new’ in the address bar)
  3. Add the complete URL of the spreadsheet to the script (line 16)
  4. Add your email address to the script (line 17)
  5. Preview
  6. Schedule to run hourly/daily.

 

/**
*
* Past Violations Alert
*
* Creates a report indicating which ads are disapproved because of 'Past Violations'
* Sends an alert via email whenever ads are disapproved for 'Past Violations'
*
* @author: Nils Rooijmans
*
* contact nils@nilsrooijmans.com for questions and the MCC version of the script 
*/
 

// CHANGE SETTINGS HERE

var SPREADSHEET_URL = "";  //insert a new blank spreadsheet url between the quotes
var EMAIL = ""; //insert your email adresses between the quotes


// NO CHANGES NEEDED BELOW THIS LINE

var SHEET_REPORT_HEADER = [
    "Campaign Name", 
    "AdGroup Name", 
    "AdID",
    "Ad Type",
    "Ad Status",
    "Policy Findings"
  ];


function main() {

  // first we clear the report sheet and add header
  prepareSpreadsheet();  
  
  // now let's check for disapprovals
  var disapprovedAds = getDisApprovedAds();    
  
  // finally, let's report on any issues
  if (disapprovedAds.length > 0) { // there is at least one issue
    Logger.log("Total NR of Ads Disapproved: "+disapprovedAds.length);
    reportResults(disapprovedAds);
  }  
}


function prepareSpreadsheet() {

  var ss = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
  var sheet = ss.getActiveSheet();
  sheet.clear(); //remove earlies alerts
  sheet.clearConditionalFormatRules();
  sheet.appendRow(SHEET_REPORT_HEADER);
}


function getDisApprovedAds() {
  
  var issues = [];
  
  var whereClause = "WHERE ad_group_ad.policy_summary.approval_status = 'DISAPPROVED' AND campaign.status = 'ENABLED' AND ad_group_ad.status = 'ENABLED' AND segments.date DURING TODAY";
  
  var gaqlQuery = "SELECT campaign.name, ad_group.name, ad_group_ad.ad.id, ad_group_ad.ad.type, ad_group_ad.policy_summary.approval_status, ad_group_ad.policy_summary.policy_topic_entries FROM ad_group_ad "+whereClause;

  Logger.log("gaqlQuery: "+gaqlQuery);
  
  var results=AdsApp.search(gaqlQuery);   
  
  while (results.hasNext()) {
    
    var row=results.next() ;
    
    var campaignName = row.campaign.name;
    var adGroupName = row.adGroup.name;
    var adId = row.adGroupAd.ad.id;
    var adType = row.adGroupAd.ad.type;
    var approvalStatus = row.adGroupAd.policySummary.approvalStatus;
    var policyTopicEntries = row.adGroupAd.policySummary.policyTopicEntries;
    
    var policyFindings = "";
    var pastViolations = false;
    
    if (policyTopicEntries.length > 0) {
      for (var i=0; i<policyTopicEntries.length; i++) {
        var policyTopic = policyTopicEntries[i].topic;
        if (policyFindings == "") {
          policyFindings = policyTopic;
        } else {
          policyFindings = policyFindings.concat(" , "+policyTopic);
        }
        if (policyTopic.toLowerCase().indexOf('STALE'.toLowerCase()) !== -1) {
          pastViolations = true;
        }
      }      
    }
    
    Logger.log("Campaign '%s', ad group '%s', ad_id '%s', issue: '%s'", campaignName, adGroupName, adId, policyFindings);

    if (pastViolations == true) {
      issues.push([
          campaignName,
          adGroupName,
          adId,  
          adType,
          approvalStatus, 
          policyFindings
      ]);  
    }
  } 
  return issues;
}


function reportResults(results) {

    var ss = SpreadsheetApp.openByUrl(SPREADSHEET_URL);
    var sheet = ss.getActiveSheet();
    var lastRow = sheet.getLastRow();

    // write issues to sheet
    var range = sheet.getRange(lastRow+1, 1, results.length, SHEET_REPORT_HEADER.length);
    range.setValues(results);

    // send the email
    var emailBody = 
      "Number of Ads Disapproved because of 'Past Violations': " + results.length + "\n" + 
      "See details: "+ SPREADSHEET_URL + "\n\n" +
      "You may want to re-enable the ads again to genereate impressions and clicks for these ads again.\n\n" +
      "For more FREE Google Ads Scripts to improve your results and make your working day feel like a breeze, visit https://nilsrooijmans.com \n" + 
      "---\n" + 
      "This email is generated by a copy of the free Google Ads Script - Disapproved Ads Checker, (C) Nils Rooijmans \n" +
      "---\n";

    MailApp.sendEmail(EMAIL, "[GOOGLE ADS ALERT] - Disapproved Ads because of 'Past Violations'", emailBody);
}

 

Join thousands of PPC geeks who already have access:

If the button above isn’t working for you, you can sign up here to get access.