Considering the way broad match and “close variants” on exact/phrase are performing in 2025, some advertisers would like to get back some control. One way to do this is with adwords scripts. One of our favorite scripts for cleaning up the queries is an auto add negative keyword script.

advanced google ads strategies ppc scripts

This script runs a query report nightly (2-6AM recommended). The script then checks the queries which drove traffic the previous day and compares them to a list of required terms. For example a dentist might choose “dentist” “dentists” “dentistry” and “tooth whitening”. The script will check the queries and do nothing for queries like “Nashville Dentists” or “best tooth whitening near me”. The script will check the queries and add them as negative keywords for queries like “Nashville Smile Clinic” (competitor) or “orthodontist near me”.

You might be surprised at the volume of search terms which will show your ads, but do not include your keywords. Because of this, when you run a script like this the total number of negative keywords will get large quickly for many advertisers. When my campaigns approach the campaign negative keyword limit, I move the negative keywords to a list. You can also consolidate negative exact keywords by finding opportunities where multiple negative exact keywords can be replaced with one negative phrase match keyword.

Here’s the script. Simple replace the campaign name with your campaign name and the keywords with the terms which you want to ensure will be included when people see your search ads moving forward.

function main() {
  var campaignName = "{exact_campaign_name}";
  var yesterday = new Date();
  yesterday.setDate(yesterday.getDate() - 1);
  var dateString = Utilities.formatDate(yesterday, "UTC", "yyyyMMdd");
  var requiredTerms = ["keyword1", "keyword2", "keyword3",];

  var report = AdsApp.report(
    "SELECT Query " +
    "FROM SEARCH_QUERY_PERFORMANCE_REPORT " +
    "WHERE Impressions > 0 " +
    "AND CampaignName = '" + campaignName.replace(/'/g, "\\'") + "' " +
    "DURING " + dateString + "," + dateString
  );

  var rows = report.rows();
  while (rows.hasNext()) {
    var row = rows.next();
    var searchTerm = row["Query"].toLowerCase();
    var containsRequiredTerm = requiredTerms.some(function(term) {
      return searchTerm.indexOf(term) !== -1;
    });

    if (!containsRequiredTerm) {
      addNegativeKeywordToCampaign(campaignName, searchTerm);
    }
  }
}

function addNegativeKeywordToCampaign(campaignName, keyword) {
  var campaignIterator = AdsApp.campaigns()
    .withCondition("Name = '" + campaignName.replace(/'/g, "\\'") + "'")
    .get();
  if (campaignIterator.hasNext()) {
    var campaign = campaignIterator.next();
    campaign.createNegativeKeyword("[" + keyword + "]");
  }
}