Find Out If You're Impacted by Google’s Changes to Exact Match

Find Out If You're Impacted by Google’s Changes to Exact Match Hi for you all and have a nice day i like the post so i share it but if...

Find Out If You're Impacted by Google’s Changes to Exact Match

Hi for you all and have a nice day i like the post so i share it but if you want to read it from Thanks :)

Find Out If You’re Impacted by Google’s Changes to Exact Match

Exact match hasn’t meant ‘exact’ for quite some time but last week Google announced that they are further expanding the broadening of exact matchkeywords.
Exact match keywords may now also start triggering ads for searches that match the intent of the keyword.
‘Intent’ can cover a pretty wide set of searches with different degrees of overlap, so advertisers need to pay closer attention than ever to what this change does to their accounts.
And as you know, I’m all about automation.
The analysis I’ll describe is trivial to do through a robust PPC management tool. Read on for a free Google Ads script that you can use to do the analysis quickly in one account or hundreds.

A Positive Impact (On Average)

While Google provides the usual reassurance that the typical account will see benefits from this change, we all know that no account is average.
So we need to make sure that the impact we’ll see for each of the unique accounts we manage will be a positive one.

What Is Changing About Exact Match?

In 2014, plurals and misspellings were added as ‘close variants’ to phrase and exact match keywords.
Now, Google has loosened the definition of exact match even further so that it may trigger ads when the machine learning systems believe that the intent of the searcher matches the keyword of the advertiser.
Examples provided by Google include scenarios where additional words are implied, where a term paraphrases the keyword, or where the words indicate the same intent.
Exact match changes in Google Ads
Whereas plurals and misspellings were fairly straightforward to understand and to some degree predict, similar intent is broader and may warrant paying closer attention.
The other part worth paying attention to is that similar intent may not equate to similar value.
For reasons that can be hard to grasp, even minor differences between keywords can equate to big differences in conversion rates.
This is even true for plurals and singulars so it’s definitely a good idea to confirm with your data that using the word ‘campsites’ vs ‘camping’ performs similarly. If not, then they should be managed as separate keywords with different bids.

Query Management Is a Must

Most of us have worked with Google long enough to understand that change is a constant for advertisers.
So rather than speculating about the real intent of Google, I think it’s more productive to take this change in stride and update our management processes to take advantage of the potentially high-quality traffic this change could bring.
Specifically, you need to make sure that your process of periodically evaluating queries continues to be done.
This process will help you find new negative keywords as well as high-quality queries that should be added as managed keywords.

Should You Be Worried? Let’s Find Out!

This type of change is causing some buzz.
Even if your process is ready to deal with any new queries that your ads start showing for, your boss or client may be uneasy.
Hey, maybe you’re even a bit uneasy because you’d like to look beyond those hypothetical examples we got from Google about keywords for “camping in Yosemite”.
So let’s take a look at how this change is impacting your account.

1. Using the Ads Interface to Investigate

To get a sense of the impact this change will have on your account, and how misspellings and plurals are already impacting your account since the change in 2014, you can refer to the Search Terms report in Google Ads.
Be sure to add the Keyword column so you can see which keyword triggered a particular search term.
Search terms analysis in Ads UIFind out what keywords triggered close variant exact matches in Google Ads in the Search Terms report

This Report Has a Few Shortcomings

The Match Type column refers to how the keyword matched the query, and not the match type of the keyword itself. This is one of those nuances in Google Ads; match type can refer to two very different things.
For example, a broad match keyword could be an exact match to a query when it is exactly the same as the broad keyword. While the broad match keyword is eligible to trigger ads for a wide range of searches, some subset of all those searches match the keyword exactly, and hence are reported as exact matches by Google.
So the only way to see the match type of the keyword is to look at the special characters in the Keyword column. For example, square brackets around the keyword mean it’s an exact match keyword.
This limitation makes it a bit harder to do a quick analysis of how exact match keywords are getting matched to close variants. And if you try to filter the keywords that contain the text ‘[‘, Google says there are no matches since the brackets are not technically part of the keyword text.
The other limitation I see is that the report only contains the performance metrics of the queries. And while you can certainly use this data to weed out low performing queries, I like doing a slightly deeper analysis that also takes into account the relative performance of the query compared to that of the keyword.

2. Doing the Analysis in Spreadsheets

As is usually the case, the analysis we really want to do takes us into spreadsheets. And you wonder why spreadsheets remain the favorite tool of many PPC marketers?!
The methodology is as follows:
  • Download a keyword performance report (including the keyword match type).
  • Download the search terms performance report.
  • Do a VLOOKUP to match every search term to the keyword that triggered it.
  • Get all the keyword and query data for each query into individual rows.
  • Filter the data to do the analysis.
There’s nothing particularly difficult about doing this analysis in a spreadsheet but all these manual steps are a bit tedious.
So let’s go and automate this.

3. Analyze the Close Variant Impact on Your Ads with Google Ads Scripts

Thanks to Google Ads Scripts, you can automate the analysis so that you can easily replicate it for other accounts you manage.
And as Google rolls out more changes to the algorithm, you can periodically check in to make sure that the impact is still positive. Just put the script on a monthly cycle so that you’ll get a new spreadsheet with the latest data to review.
Another nice benefit of scripts is that if you find the need to add negative keywords, you can automate that by adding a few more lines of code to the script.
The script also adds a match subtype column where I consider BMM (broad match modifier) to be a unique match type that is different from broad match. (Google doesn’t consider BMM to be its own match type).
Grab a copy of the script code here:
// Report on how close variants relate to your keywords in Google Ads
// Free AdWords Script courtesy of
// September 12, 2018
function main() {
// -----------------
// Edit this section with your preferences
// ----------------
var time = 'LAST_30_DAYS';
var reportVersion = 'v201802';
var emailAddresses = '';
var accountManagers = '';
var spreadsheetUrl = 'new';
var includeLevinsthein = 1; // set value to 0 if your script times out. by not adding this score, the script will run faster
// use 1 or none of the following two settings to limit the campaigns analyzed
var campaignNameContains = ""; // this is NOT case sensitive
var campaignNameDoesNotInclude = ""; // this is NOT case sensitive
// -------------------
// Don't make edits after this unless you know how to write scripts
// -------------------
var map = new Array();
// Get Campaign IDs
var campaignsToCheck = new Array();
if(campaignNameDoesNotInclude) {
if(campaignNameDoesNotInclude.indexOf("'") != -1)
var doesNotContainString = '"' + campaignNameDoesNotInclude + '"';
} else {
var doesNotContainString = "'" + campaignNameDoesNotInclude + "'";
var campaigns = AdWordsApp.campaigns()
.withCondition('Name DOES_NOT_CONTAIN_IGNORE_CASE ' + doesNotContainString)
.withCondition('Status != REMOVED')
} else if(campaignNameContains) {
if(campaignNameContains.indexOf("'") != -1) {
var containsString = '"' + campaignNameContains + '"';
} else {
var containsString = "'" + campaignNameContains + "'";
var campaigns = AdWordsApp.campaigns()
.withCondition('Name CONTAINS_IGNORE_CASE ' + containsString)
.withCondition('Status != REMOVED')
} else {
var campaigns = AdWordsApp.campaigns()
.withCondition('Status != REMOVED')
while(campaigns.hasNext()) {
var campaign =;
var campaignId = campaign.getId();
// Keywords
var query =
'SELECT Id, KeywordMatchType, Criteria, Clicks, Impressions, Cost, ConversionValue, Conversions, AveragePosition, Ctr, AverageCpc, AdGroupName, CampaignName, CampaignId, AdGroupId ' +
'WHERE Impressions > 0 ' +
'AND CampaignId IN ' + JSON.stringify(campaignsToCheck) + " " +
'DURING ' + time;
var report =,{apiVersion: reportVersion});
var rows = report.rows();
while(rows.hasNext()) {
var row =;
var adGroupId = row['AdGroupId'];
var id = row['Id'];
var criteria = row['Criteria'];
if(criteria.indexOf('+') != -1) {
var subMatchType = "BMM";
} else {
var subMatchType = row['KeywordMatchType'];
var key = adGroupId + "-" + id;
if(!map[key]) {
map[key] = new Object();
map[key].keyword = new Object();
map[key].searchTerms = new Array();
map[key].keyword.criteria = row['Criteria'];
map[key].keyword.clicks = parseInt(row['Clicks'],10);
map[key].keyword.impressions = parseInt(row['Impressions'],10);
map[key].keyword.cost = getFloat(row['Cost']);
map[key].keyword.conversions = getFloat(row['Conversions']);
map[key].keyword.ctr = getFloat(row['Ctr']);
map[key].keyword.averagePosition = getFloat(row['AveragePosition']);
map[key].keyword.averageCpc = getFloat(row['AverageCpc']);
map[key].keyword.conversionValue = getFloat(row['ConversionValue']);
map[key].keyword.matchType = row['KeywordMatchType'];
map[key].keyword.subMatchType = subMatchType;
map[key].keyword.campaignName = row['CampaignName'];
map[key].keyword.adGroupName = row['AdGroupName'];
// Search Terms
var query =
'SELECT KeywordId, KeywordTextMatchingQuery, Query, QueryMatchTypeWithVariant, Clicks, Impressions, Cost, ConversionValue, Conversions, AveragePosition, Ctr, AverageCpc, AdGroupName, CampaignName, CampaignId, AdGroupId ' +
'WHERE Impressions > 0 ' +
'AND CampaignId IN ' + JSON.stringify(campaignsToCheck) + " " +
'DURING ' + time;
var report =,{apiVersion: reportVersion});
var rows = report.rows();
while(rows.hasNext()) {
var row =;
var adGroupId = row['AdGroupId'];
var id = row['KeywordId'];
var query = row['Query'];
var key = adGroupId + "-" + id;
if(!map[key]) {
// most likely a shopping campaign
// Logger.log("query not associated with kw in campaign: " + row['CampaignName']);
} else {
if(!map[key].searchTerms[query]) {
map[key].searchTerms[query] = new Object();
map[key].searchTerms[query].matchTypeVariant = row['QueryMatchTypeWithVariant'];
map[key].searchTerms[query].clicks = parseInt(row['Clicks'],10);
map[key].searchTerms[query].impressions = parseInt(row['Impressions'],10);
map[key].searchTerms[query].cost = getFloat(row['Cost']);
map[key].searchTerms[query].conversions = getFloat(row['Conversions']);
map[key].searchTerms[query].ctr = getFloat(row['Ctr']);
map[key].searchTerms[query].averagePosition = getFloat(row['AveragePosition']);
map[key].searchTerms[query].averageCpc = getFloat(row['AverageCpc']);
map[key].searchTerms[query].conversionValue = getFloat(row['ConversionValue']);
map[key].searchTerms[query].impressions = parseInt(row['Impressions'],10);
map[key].searchTerms[query].campaignName = row['CampaignName'];
// Spreadsheet
var reportDate = new Date();
var dateForFilename = reportDate.yyyymmdd();
if(spreadsheetUrl.toLowerCase().indexOf("new") != -1)
var spreadsheet = SpreadsheetApp.create("Keyword Analysis - " + AdWordsApp.currentAccount().getName() + " - " + dateForFilename + " (" + time + ")");
var spreadsheetUrl = spreadsheet.getUrl();
var spreadsheet = SpreadsheetApp.openByUrl(spreadsheetUrl);
if(accountManagers && accountManagers!=""){
var accountManagersArray = accountManagers.replace(/\s/g, "").split(",");
// Sheet for Keyword Report
//get all sheets except first and delete them and insert new sheets every time to avoid name error
var allSheets = spreadsheet.getSheets();
for(var i=1,len=allSheets.length;i<len;i++){
var kwSheet = allSheets[0];
kwSheet.appendRow(["Campaign Name", "Ad Group Name", "Match Type", "Sub Match Type", "Keyword", "Search Term", "Query Match Type with Variant", "Levenshtein distance",
"KW Clicks", "KW Impressions", "KW Cost", "KW CTR", "KW Avg. CPC", "KW Conversions", "KW Conv. Value", "KW Avg Pos.",
"Query Clicks", "Query Impressions", "Query Cost", "Query CTR", "Query Avg. CPC", "Query Conversions", "Query Conv. Value", "Query Avg Pos."]);
// Render
for(var key in map) {
var criteria = map[key].keyword.criteria;
var matchType = map[key].keyword.matchType;
var subMatchType = map[key].keyword.subMatchType;
var kwClicks = map[key].keyword.clicks;
var kwImpressions = map[key].keyword.impressions;
var kwConversions = map[key].keyword.conversions;
var kwCost = map[key].keyword.cost;
var kwCtr = map[key].keyword.ctr;
var kwAverageCpc = map[key].keyword.averageCpc;
var kwConversionValue = map[key].keyword.conversionValue;
var kwAveragePosition = map[key].keyword.averagePosition;
var campaignName = map[key].keyword.campaignName;
var adGroupName = map[key].keyword.adGroupName;
for(var query in map[key].searchTerms) {
var queryClicks = map[key].searchTerms[query].clicks;
var matchTypeVariant = map[key].searchTerms[query].matchTypeVariant;
//Logger.log(criteria + " | " + query + " | " + matchType + " " + matchTypeVariant);
if(matchType.toLowerCase() != matchTypeVariant.toLowerCase()) {
//var difference = getDifference(criteria, query);
//var diffLen = difference.length;
var rawCriteria = criteria.replace(/\+/g,"");
if(includeLevinsthein) {
var diffLen = levDist(rawCriteria, query);
} else {
var diffLen = "";
var queryClicks = map[key].searchTerms[query].clicks;
var queryImpressions = map[key].searchTerms[query].impressions;
var queryConversions = map[key].searchTerms[query].conversions;
var queryCost = map[key].searchTerms[query].cost;
var queryCtr = map[key].searchTerms[query].ctr;
var queryAverageCpc = map[key].searchTerms[query].averageCpc;
var queryConversionValue = map[key].searchTerms[query].conversionValue;
var queryAveragePosition = map[key].searchTerms[query].averagePosition;
//Logger.log(criteria + " " + matchType + " " + query + " " + matchTypeVariant + " " + kwClicks + " " + " " + diffLen);
kwSheet.appendRow([campaignName, adGroupName, matchType, subMatchType, "'"+criteria, query, matchTypeVariant, diffLen,
kwClicks, kwImpressions, kwCost, kwCtr, kwAverageCpc, kwConversions, kwConversionValue, kwAveragePosition,
queryClicks, queryImpressions, queryCost, queryCtr, queryAverageCpc, queryConversions, queryConversionValue, queryAveragePosition]);
// Notify
var body = "your report is ready at: " + spreadsheetUrl;
MailApp.sendEmail(emailAddresses, "", "Your match type analysis is ready", body);
// date functions
Date.prototype.yyyymmdd = function() {
var yyyy = this.getFullYear().toString();
var mm = (this.getMonth()+1).toString(); // getMonth() is zero-based
var dd = this.getDate().toString();
return yyyy + (mm[1]?mm:"0"+mm[0]) + (dd[1]?dd:"0"+dd[0]); // padding
function getFloat (input) {
if(!input || input == "" || typeof(input) === 'undefined') var input = "0.0";
input = input.toString();
var output = parseFloat(input.replace(/,/g, ""));
return output;
// Function: levDist
// Author James Westgate (
// Source:
// License: CC-BY-SA (
function levDist(s, t) {
var d = []; //2d matrix
// Step 1
var n = s.length;
var m = t.length;
if (n == 0) return m;
if (m == 0) return n;
//Create an array of arrays in javascript (a descending loop is quicker)
for (var i = n; i >= 0; i--) d[i] = [];
// Step 2
for (var i = n; i >= 0; i--) d[i][0] = i;
for (var j = m; j >= 0; j--) d[0][j] = j;
// Step 3
for (var i = 1; i <= n; i++) {
var s_i = s.charAt(i - 1);
// Step 4
for (var j = 1; j <= m; j++) {
//Check the jagged ld total so far
if (i == j && d[i][j] > 4) return n;
var t_j = t.charAt(j - 1);
var cost = (s_i == t_j) ? 0 : 1; // Step 5
//Calculate the minimum
var mi = d[i - 1][j] + 1;
var b = d[i][j - 1] + 1;
var c = d[i - 1][j - 1] + cost;
if (b < mi) mi = b;
if (c < mi) mi = c;
d[i][j] = mi; // Step 6
//Damerau transposition
if (i > 1 && j > 1 && s_i == t.charAt(j - 2) && s.charAt(i - 2) == t_j) {
d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + cost);
// Step 7
return d[n][m];

Script Settings

Really the only things you should edit are the email addresses that need to get an email when a report is ready and the usernames of everyone who should be allowed to access the report that is generated in Google Sheets.
So update the variables ‘emailAddresses’ and ‘accountManagers’ and leave everything else as-is unless you’re familiar with scripts and you know what you’re doing.
var time = ‘LAST_30_DAYS’;
var reportVersion = ‘v201802’;
var emailAddresses = ‘’;
var accountManagers = ‘’;
var spreadsheetUrl = ‘new’;

The Output of the Script

Here’s an example of the data you’ll get:
spreadsheet with close variant ads dataThis Google spreadsheet is generated by an Ads Script that merges query and keyword data to make it easy to see which close variants Google is expanding to for phrase and exact match keywords.
I’ve already used filters in Sheets to see only exact match keywords that were matched to a close variant. In this account the only variants are typos and plurals.
I’m going to continue monitoring this account with the script to find out what words Google considers as having the same intent.

Counting the Proximity Between the Query & Keyword

In the output, I wanted a way to more easily see how aggressive close variants are. In other words, how far they are from the keyword.
I figured one way to do this analysis is by counting the number of differences between the query and the keyword.
The Levenshtein distance seemed like a good measure to use as it counts the number of characters that need to be changed to transform one string (the keyword) into another string (the query).
In a pluralization, you would expect the difference to usually be one character (the addition or removal of the letter ‘s’ in English). Typos will usually consist of somewhere between 1 and 3 incorrectly typed characters.
So by looking at variants where the Levenshtein distance is in the range of 1 to 3, I can find the typical close match variants Google has now been doing for several years.
By looking for higher distances, I will be able to find where the words have been changed to ones with similar intent.


As Google is always updating its ad system, it’s critical for the humans overseeing the accounts to take on the role of the pilot who oversees that the automation is doing its job well.
Tools like Google Ads scripts are a great way to make that job easier by pointing out potential issues so that the account manager doesn’t need to merely trust the automation, nor check it manually.
I hope my script helps you do your job better and in less time.

Image Credits
All screenshots taken by author, September 2018



Bing,1,Blogger,31,Blogging Tips,89,Book Marketing,1,CMS,2,Computer,4,CSS,1,Google,13,Google AdSense,5,HTML,7,Info graphic,1918,Joomla,1,Making Money,4,Marketing,1992,Mobile phone reviews,2,PHP,7,Search Engines,24,SEO,2014,Social Network,1795,Tips,2059,WordPress,28,
just free learn : Find Out If You're Impacted by Google’s Changes to Exact Match
Find Out If You're Impacted by Google’s Changes to Exact Match
just free learn
Loaded All Posts Not found any posts VIEW ALL Readmore Reply Cancel reply Delete By Home PAGES POSTS View All RECOMMENDED FOR YOU LABEL ARCHIVE SEARCH ALL POSTS Not found any post match with your request Back Home Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sun Mon Tue Wed Thu Fri Sat January February March April May June July August September October November December Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec just now 1 minute ago $$1$$ minutes ago 1 hour ago $$1$$ hours ago Yesterday $$1$$ days ago $$1$$ weeks ago more than 5 weeks ago Followers Follow THIS CONTENT IS PREMIUM Please share to unlock Copy All Code Select All Code All codes were copied to your clipboard Can not copy the codes / texts, please press [CTRL]+[C] (or CMD+C with Mac) to copy