play watch

Setting Up Auto-Negatives

This guide covers how to set up and strategically implement an auto-negatives Ad Script for shopping and search campaigns.

Guide Summary

See also:

  • 🚧 How To Set Up & Run An Ad Script

What Auto-Negatives Are

When we refer to auto-negatives, we refer to the following system.

  • A Google Sheet that defines the exact keywords we want to allow in our search queries…
  • …and a scheduled Ad Script that adds negatives of the search queries that don’t precisely match those keywords.

When this system is set up, we refer to it as auto-negatives.

Terms To Know

  • Search query · The terms that a shopper typed into Google’s search which triggered our ad. Also referred to a search terms by Google.
    • Example: If the shopper typed “buy runnning shoes” and it triggers our ad, that is the search query (including the typo). Learn more.
  • Negatives · Keywords that we set to exclude our ads to appear for.
    • Example of how negatives work (note the typo in ‘runnning’):
Search QueryNegativeMatch TypeResult
buy runnning shoesshoesBroadSearch query blocked
buy runnning shoes“shoes”PhraseSearch query blocked
buy runnning shoes[shoes]ExactSearch query not blocked
buy runnning shoesrunningBroadSearch query not blocked
buy runnning shoes“running”PhraseSearch query not blocked
buy runnning shoes[running]ExactSearch query not blocked
buy runnning shoes“runnning”PhraseSearch query blocked
  • Ad Script · JavaScript code that can be automated, written to execute bids changes, pause ad groups, and add keywords (and negative keywords) directly instead of manually within your Google Ads account.
  • Positive Keywords · Terms that we set as a requirement that the search query must contain.
    • Example: We set ‘roses’ as a positive keyword. If a shopper searches ‘red roses’, then it has matched the criteria. If a shopper searches ‘red rose’, it has failed the criteria.

How Auto-Negatives Work

Auto-negatives are set by:

  • installing and authorizing an Ad Script (shared below)
  • setting up a properly templated Google Sheet
  • creating the positive keywords to be applied at campaign and ad group levels
  • running the Ad Script

Once the script is running (typically on a regular schedule), it will scan the search queries of the campaigns and ad groups we’ve set it to, and it will add any search query that fails to meet our criteria (positive keywords and number of matches) as negatives.

That means we can filter out poor search queries from future ad impressions and clicks, thereby saving money and improving conversion rates over time as the negative lists become robust in filtering out what we deem as unqualified traffic.

A Simple Demonstration

This demonstration is to show, in a simplified way, what the outcome is of running auto-negatives.

Let’s say you have a Shopping campaign set up like this:

  • Campaign name: Roses
    • Ad group name: Red Roses
    • Ad group name: Blue Roses
    • Ad group name: White Roses

You set up your sheet like this:

Number of matches:132
Ad Group:Red RosesBlue RosesWhite Roses
Keywords:red rosebluewhite
 red rosesrosesroses

When the ad script runs, it will review the search queries that have been reported for each ad group. For each search query, it will determine if it matches the set criteria, and if it doesn’t, it will add the search query as a negative to the ad group.

The number of matches indicate how many of the positive keywords need to be present in the query. If it’s set as ‘1’, the search query will need to contain 1 of the positive keywords in the list for that ad group, or else it won’t meet the criteria and will be added as a negative. If it’s set as ‘2’, the search query will need to contain 2 of the positive keywords in the list for that ad group, or else it won’t meet the criteria and will be added as a negative.

Example #1

Let’s look at the Red Roses search queries first, and see how they met criteria and generated new negatives. Remember, its number of matches is set to 1.

Search QueryMet Criteria?Result
buy red rosesYesNo negative added
order roses onlineNo[order roses online] negative added
roses are redNo[roses are red] negative added
drawing of a red roseYesNo negative added
rose redNo[rose red] negative added

Example #2

Let’s look at the Blue Roses search queries next, and see how they met criteria and generated new negatives. Remember, its number of matches is set to 3.

Search QueryMet Criteria?Result
buy blue rosesYesNo negative added
order blue roses onlineNo[order blue roses online] negative added
roses are red violets are blueNo[roses are red violets are blue] negative added
roses blue buyYesNo negative added
buy blue roseNo[buy blue rose] negative added

Example #3

Let’s look at the White Roses search queries now, and see how they met criteria and generated new negatives. Remember, its number of matches is set to 2.

Search QueryMet Criteria?Result
buy white rosesYesNo negative added
order a white rose onlineYesNo negative added
roses are red lilies are whiteYesNo negative added
whitest rosesNo[whitest roses] negative added
rose whiteYesNo negative added

⚠️ Super Major Vital Important

It’s critical that you fully understand how the criteria are met in each of these cases. Without understanding the logic of each example, you will make terrible mistakes in your setup.

When To Use Auto-Negatives

Simply put, auto-negatives should be used when we know precisely which terms we want to allow into our search queries.

We shouldn’t use auto-negatives when we want to let Google do its job of matching any relevant queries to our keywords.

It comes down to a trust thing. Do we trust Google to understand which search terms to match to our keywords? Many professional account managers have seen inexcusably irrelevant terms getting matched to their keywords, and have very low trust as a result. This is perfectly valid, as no one likes to waste money on bad traffic.

It’s also valid to trust Google over the long term, and let its machine learning do very stupid things until it learns not to. If you’re a fat budget company with little interest in short term cost efficiency, then auto-negatives isn’t for you.

For the rest of us spend thrifts, auto-negatives helps us spend less on the bad so that we can spend more on the good.

Standard Shopping Campaigns

The biggest reason auto-negative scripts were written by professionals was due to Standard Shopping campaigns. You cannot target b keywords with this campaign, and must rely on Google’s best shots at matching search queries to your products.

Google can be truly awful at doing this, which is why it’s vital to a well-managed account that the search terms that shoppers have used to trigger your ads are continuously reviewed, and appropriate negatives added.

Setting up auto-negatives is a convenient way of automating this process, and handling enormous lists of search queries with ease, speed, and regularity.

Search Campaigns

With search campaigns, we can target keywords, of course. But over time, Google trusts us less and less to get it right, and they just take these keywords as general suggestions. Auto-negatives gives us back some semblance of control against their loose “close match” matches. Especially when we need to be precise in our matching for specific niche terms.

DSA Campaigns

Actually, not all search campaigns use keywords for targeting.

The Dangers of Using Auto-Negatives

Auto-negatives can go oh so wrong. By misunderstanding the logic of how they work, or making a mistake in the strategy, or flubbing a setting, you can at best be less efficient, and at worst, lose a lot of money and potential revenue.

How Can Things Go Wrong?

  • misunderstanding the logic of the ‘Number of matches’ and its application to the list of positive keywords
  • setting too few positive keywords
  • setting too many positive keywords
  • setting the wrong positive keywords
  • incorrectly naming the campaign and ad groups in the sheet
  • changing the names of the campaign or ad groups in Google Ads and forgetting that this affects the auto-negatives setup
  • allowing the ad group negatives to reach 20,000 (their max)
  • set what of the other settings inappropriately

Furthermore, overusing auto-negatives where they’re not necessary can be very unwise. Google actually does not what it’s doing for matching shoppers to relevant ads, at least in general. Making things too restrictive for what you’ll allow for your search terms can inhibit your growth.

But Don’t Worry, You Got This

Just be as careful with this as you can be. Less competent and beautiful persons than yourself have made this work. Think it all through thoroughly, triple-check your work, and check the results fanatically after you activate it.

How To Set Up Auto-Negatives

This is a step by step instruction guide for setting up auto-negatives.

Setting Up the Google Sheet

  1. Click this link.
  2. Click Make a copy to create a new sheet for your auto-negatives
Google Sheets
  1. Rename the sheet
  2. Type the exact name of the campaign you’ll be applying these auto-negatives to in cell A2.
  3. Leave the following settings at their defaults, for now (we’ll cover these in a later guide):
    • Min Query Clicks = (blank)
    • Max Query Conversions = (blank)
    • Date Range = LAST_30_DAYS
    • Negative Match Type = Exact
    • Campaign Level Queries = No
  4. Type the exact name of the first ad group you’ll be applying these auto-negatives to in cell B5.
  5. Set the Number of Matches for positive keywords that you want the search queries to meet in cell B4. 1, 2, or 3. (It’s rare you will find the need to go above 3 for this logic.)
  6. Type in your positive keywords starting from cell B7 down.
  7. Moving right one column, repeat steps 6 through 8 for the next ad group(s).
  8. Once you’ve added all the ad groups that you want to apply these auto-negatives to, you can change the name of the tab to indicate the campaign this tab pertains to. This isn’t necessary, but if you want this document to cover many campaigns, doing this will help with your organization.
  9. If you have another campaign you’d like to set up for auto-negatives, go to the next tab and repeat the above steps 4 through 10.
  10. If you…
    1. want to create tabs to cover even more campaigns, click the down arrow beside the tab name, go to Copy to > Existing spreadsheet. This will create an exact copy, and you can delete the copied information you entered on this new tab and write in your next campaign’s information.
    2. don’t want to cover any new campaigns, simply delete the second tab called Campaign Name #2.

Setting Up the Ad Script

  1. In your Google Ads account, go to Tools and settings, then under Bulk Actions click Scripts.
  2. Create a new script by clicking the blue (+) icon.
  3. Delete the 3 current lines of code.
  4. Copy the following code and paste it in.

var SPREADSHEET_URL = “XXXXXXXXXXX”; //template here:
var SS = SpreadsheetApp.openByUrl(SPREADSHEET_URL);

function main() {

var timeStampCol = 7

var sheets = SS.getSheets();

var times = new Object();
var timesArray = [];
//get timestamps
var i = 0;
for(var sheetNo in sheets){

var sheet = sheets[sheetNo];

var timestamp = sheet.getRange(1, timeStampCol).getValue();

times[timestamp] = sheet.getName();
//first run
var oldenTimes = new Date();
oldenTimes.setDate(oldenTimes.getDate() – (1000+i));
times[oldenTimes] = sheet.getName();



//loop through sheets, starting with the earliest time
timesArray = timesArray.sort(function(a, b){return a-b});

for(var time in timesArray){
var sheetName = times[timesArray[time]];
Logger.log(“Checking sheet: ” + sheetName);
var sheet = SS.getSheetByName(sheetName);

var SETTINGS = {}
SETTINGS[“CAMPAIGN_NAME”] = sheet.getRange(“A2”).getValue()
SETTINGS[“MIN_QUERY_CLICKS”] = sheet.getRange(“B2”).getValue()
SETTINGS[“MAX_QUERY_CONVERSIONS”] = sheet.getRange(“C2”).getValue()
SETTINGS[“DATE_RANGE”] = sheet.getRange(“D2”).getValue()
SETTINGS[“NEGATIVE_MATCH_TYPE”] = sheet.getRange(“E2”).getValue()
SETTINGS[“CAMPAIGN_LEVEL_QUERIES”] = sheet.getRange(“F2″).getValue()==”Yes” ? true : false

Logger.log(“Settings: “+ JSON.stringify(SETTINGS))

var adGroups = [];
var adGroupMins = [];
var adGroupColumnNumbers = [];
var col = 2;

var numMatchesRow = 4
var adGroupNameRow = 5
var negativeListNameRow = 6
var firstAdGroupRow = 7

//grab adGroup data from sheet,store in arrays
while(sheet.getRange(numMatchesRow, col).getValue()){
adGroups.push(sheet.getRange(adGroupNameRow, col).getValue());
adGroupMins.push(sheet.getRange(numMatchesRow, col).getValue());

//loop through the adGroups listed in the sheet
for(var ag in adGroups){

var adGroupName = adGroups[ag];
Logger.log(“Checking AdGroup: “+ adGroupName);
var row = firstAdGroupRow;

var keywords = [];
//get the “positive” keywords from the sheet, for this adGroup
while(sheet.getRange(row, adGroupColumnNumbers[ag]).getValue()){

keywords.push(sheet.getRange(row, adGroupColumnNumbers[ag]).getValue());

Logger.log(“‘Positive Keywords' from sheet: “+ keywords);
//get the search queries from the campaign, we'll check against these

var query = “SELECT Query ” +
+ ” WHERE CampaignName = ‘”+SETTINGS[“CAMPAIGN_NAME”] + “‘”

query+= ” AND Clicks >= ” + SETTINGS[“MIN_QUERY_CLICKS”]

query+= ” AND Conversions < ” + SETTINGS[“MAX_QUERY_CONVERSIONS”]

query+= ” AND AdGroupName = ‘” + adGroupName + “‘”




log(“query: ” + query)
var report =;

var rows = report.rows();
var negs = [];
//loop through this campaign's queries, add anything which doesn't contain our positive keywords to the negs array (these will be added as negatives later)
var nxt =;
var q = nxt.Query;
var matches = 0;
var count = 0;

//loop through the positive keywords (from the sheet)
for(var k in keywords){
//if > min (e.g. 2) of the keywords are in the search term, then neg it
// Logger.log(“Checking against keyword: ” + keywords[k]);
// Logger.log(“Checking against term: ” + q);
//if the keyword is in the query, we have a match. match++
if(q.indexOf(keywords[k]) > -1){
//Logger.log(nxt.Query + ” – ” + q.indexOf(keywords[k]) + ” – ” + keywords[k] );
// Logger.log(“matches: ” + matches);
// Logger.log(“count: ” + count + ” – ” + keywords.length);

//if we have reached the end of the positive keywords i.e. checked them all
//and if the number of matches is leSS than the minimum number of matches for the adgroup (specified on the sheet)
//then add the query to the negatives array
if(matches < adGroupMins[ag] && count == keywords.length){
// Logger.log(count + ” – ” + keywords.length);
//Logger.log(“adding negative: ” + nxt.Query);


Logger.log(“Found a total of “+negs.length+” negative keywords to add”)
Logger.log(“Adding the negative keywords…”)

var adGroupFound = false;
col = 2;

var negativeSelectedListName = sheet.getRange(negativeListNameRow, col).getValue();

if (negativeSelectedListName) {
var negativeKeywordListSelector = AdsApp.negativeKeywordLists()
.withCondition(“Name CONTAINS ‘” + negativeSelectedListName + “‘”);

var negativeKeywordListIterator = negativeKeywordListSelector.get();

while (negativeKeywordListIterator.hasNext()) {
var negativeKeywordList =;

for(var neg in negs){
var neg = addMatchType(negs[neg],SETTINGS)

} else {
//we have the negs. Now add them to the adgroup…
var iterTypes = [“Shopping”, “Text”]

for(var t in iterTypes){

var type = iterTypes[t]


var adGroupIterator = AdWordsApp.shoppingAdGroups()


var adGroupIterator = AdWordsApp.adGroups()


adGroupIterator = adGroupIterator
.withCondition(“Name = ‘”+adGroupName+”‘”)
.withCondition(“CampaignName = ‘”+SETTINGS[“CAMPAIGN_NAME”] +”‘”)


adGroupFound = true;

var adGroup =;

for(var neg in negs){
var neg = addMatchType(negs[neg],SETTINGS)


}//end ad types loop

Logger.log(“AdGroup ‘” + adGroupName + “‘ in Campaign ‘” +SETTINGS[“CAMPAIGN_NAME”] + “‘ not found in the account. Check the AdGroup name is correct in the sheet.”);



var date = new Date();
sheet.getRange(1, timeStampCol).setValue(date);

}//end time array loop

}//end main

function addMatchType(word,SETTINGS){
word = word.trim();
}else if(SETTINGS[“NEGATIVE_MATCH_TYPE”].toLowerCase()==”bmm”){
word = word.split(” “).map(function (x){return “+”+x}).join(” “).trim()
}else if(SETTINGS[“NEGATIVE_MATCH_TYPE”].toLowerCase()==”phrase”){
word = ‘”‘ + word.trim() + ‘”‘
}else if(SETTINGS[“NEGATIVE_MATCH_TYPE”].toLowerCase()==”exact”){
word = ‘[‘ + word.trim() + ‘]'
throw(“Error: Match type not recognised. Please provide one of Broad, BMM, Exact or Phrase”)
return word;

function log(x){Logger.log(x)}

  1. Go back to your Google Sheet in another tab of your browser, click the green Share button at the top right of the page. In the Get link section, click Change, then change it to Anyone with the link, and Editor.
  2. Click Copy link, and go back to your Google Ads tab.
  3. In the first line of the code, replace XXXXXXXXXXX with the URL you copied. Be sure to paste it within the “” marks.
  4. Name your script.
  5. Click SAVE at the bottom right of the screen.
  6. Click PREVIEW.
  7. Google will then show a yellow bar at the bottom of the page. Click AUTHORIZE, then verify your account.
  8. You will now be able to see the output of what the auto-negatives script will do.
  9. Once you’re satisfied, click RUN.
  10. You’ll then be shown the SCRIPT HISTORY page. Make sure your timeframe includes today so that you can see your currently running script.
  11. Once it’s finished, review the results.
  12. If you’re happy with the results, go to the SCRIPTS page and set the frequency for your script to run daily, at whatever time you like.
  13. Return to the Google Sheet and set the Date Range to YESTERDAY in cell D2. This is because you’ve already run the script to review search queries for the past 30 days, there is no need for it to go past yesterday now (it’s best to have scripts run as quickly as possible).

Determining Your Positive Keywords

Choosing which positive keywords seems like an easy thing to do. You assume you know the words you should allow in a search term, and assume if it doesn’t contain your positive keywords, it’s not fit for you ad group. Well yes, this generally works.

The danger is that you exclude qualified shopper traffic with typos, misspellings, and alternate word orders.

Let’s say you’re selling red roses, and your positive keywords are red roses and red rose, with the number of matches set to 1 (the search query must contain one of those terms). Let’s review a hypothetical list of search terms.

Search termsQualified?Met criteria?
red roses
buy dozen roses
red eoses
roses are red bouquet
where can i buy roses that are red
roses for valentines
red rosses
is pinkish red rose a red wine or white
la vie en rose red lingerie
why are roses red
tips for a good red rose bush garden
red roses illustration

As you can see, search terms that have a purchase intent for the product would get excluded, and unqualified terms can slip through.

This is why it’s most ideal to set up positive keywords after you have search data to review. It allows you to spot the common search permutations people use to shop for your products.

Of course, your first activity after reviewing the above list should be to add the following general negatives to your campaign for roses:

  • “wine”
  • “wines”
  • “lingerie”
  • “la vie en rose”
  • “why”
  • “tips”
  • “bush”
  • “bushes”
  • “garden”
  • “gardens”
  • “gardening”
  • “illustration”
  • “illustrations”

Of course. But that’s a separate guide.

Small Accounts

If you’re managing a small account (traffic lower than 1,000 clicks per day), then the above setup of red roses and red rose as positive keywords may be a perfectly fine setup. Why? Because you probably don’t have the budget to broadly go after the market anyway, so chasing typos, misspellings, and different word orders may not be a suitable investment of time and money.

Determining Positive Keywords for Larger Accounts

For larger accounts, it’s recommended that you review as much search query data as possible. Also an N-Gram analysis. What you’re looking for are terms you want to allow into your search queries. You won’t be able to cover it all, but you can make sure a significant amount of qualified traffic is adequately covered.

Auto-Negatives Checklist

For each ad group column…

If you’re applying it to just one campaign…

If you’re applying it to more campaigns…

On the first run for the script, you want it to cover the last 30 days.

On the second run for the script, right after the first run, you want it to cover today thereafter. That way, the maximum time that a disqualified search term can trigger an ad is basically 1 hour.

Add Your Comments & Questions Below
Notify of
Inline Feedbacks
View all comments
Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors

Subscribe to Our Newsletter to Improve Your eCommerce Digital Marketing!

Thank you for your interest in our newsletters. We will send you only the most important news and updates. No spam, we promise.

We are committed to protecting your privacy, as described in our Privacy policy.

What’s your goal today?

1. Hire us to grow your ecommerce store

We’ve generated millions for our clients, using the methods we’ve developed over years with a singular focus on Google Ads for ecommerce. To discover how we can help grow your business:

Claim your FREE website strategy session with one of our renowned experts.

2. Learn & develop your ecommerce skills

Watch our highly regarded YouTube channel, followed by over 23,000 store owners and ecommerce learners from around the world.

You can also subscribe to our weekly email newsletter to get real-world tested growth and optimization strategies, as well as notifications on anything you may need to know as an ecommerce store owner.

Browse our blog, written and structured to be the best resource in the world for anyone starting and growing their online store. It includes strategy guides, setup instructions, checklists, and tools.

Explore our KeyCompendium, which is a comprehensive wiki of digital marketing terms. Many readers have commented on the usefulness of this content.

3. Join our team

If you want to join our team—or discover why our team members love working with KeyCommerce—then see our “Careers” page.

4. Contact us

We help ecommerce store owners around the world, so get in touch!