How Account Quality Score Can Guide AdWords Optimization

Last month, I covered four ways to use AdWords Scripts to improve AdWords account management. I didn’t share any actual code for fear of geeking out too much, but people seemed interested enough in how to use Scripts to track historical Quality Score (QS), so this month, I’ll share step-by-step instructions and give you the code needed to track your own account-level Quality Score.

But first, let me explain what account-level Quality Score is all about…

Why You Should Track Account-Level Quality Score

The Quality Score of your AdWords account is a useful gauge to monitor how good Google thinks your optimizations are. Rather than tracking the QS of every keyword in an account, which is not only tedious but also not very useful when an optimization includes new keywords and removes others, you can roll up the keyword-level data into an account-level number.

Then, when you want to know if your account is headed in the right direction, the account-level QS number can provide the answer.

Why Can’t I See Account Quality Score In AdWords?

Technically, Google does not have a metric called account-level QS; it’s not a number that’s published anywhere. It’s not just that Google hides this number from advertisers, it’s not even available to your CSR, or for that matter, Larry Page. When I worked at Google, I got asked all the time if there was a QS reset button in Sergey and Larry’s office, and no, unfortunately, there isn’t.

Because QS is based on so many historical factors, the only way to get rid of poor QS is to start running lots of ads that have better QS, thereby reducing the negative QS impact from older ads.

Account-level QS is merely a construct that helps us understand and predict how a complex prediction algorithm (the QS system) might behave under certain circumstances. AdWords’ QS is a complex learning system that tries to guess for every single query which ads users will find most useful. Those predictions use historical data to guess possible outcomes of future searches.

So, when a keyword in your account has lots of impressions, Google uses that keyword’s historical CTR from your account to make an educated guess about the future performance of that keyword, and that’s how it gets its keyword-level QS. This keyword-level QS is the only insight into QS that you get from AdWords, and keep in mind that it’s an attribute and not a stat.

In other words, even if you change the date range in AdWords, you will always get the same number, which is an indication of the current QS.

How Quality Score Is Determined For New Keywords

But, how does the QS system make a prediction when you add a new keyword to AdWords for the first time and there is no historical CTR data for that keyword in your account? How does Google then set the starting Quality Score for that keyword? It’s complicated, but part of the answer is that they look at similar signals to make their guess.

Similar data includes system-wide data about how your new keyword has performed when other advertisers used it. And, when your account has been around for some time, Google can also use its notion of how your historical performance has been compared to the expected average.

Here’s an example: Google might expect a particular new keyword to have a starting QS of 6 based on the historical CTR of all other advertisers who have used this keyword, but because they know that your account typically has a better than average CTR performance, they may boost your starting QS to a 7.

They do so under the assumption that you are likely to perform better than average for a new keyword because you’ve historically had very relevant ads for other keywords.

How Can I Calculate Account QS?

Quality Score in AdWords is reported only at the keyword level, and that’s where it’s used in combination with the bid to determine the ad rank. One way to think about account-level QS is as an impression-weighted average.

In last month’s post, I explained the math behind calculating the account QS. Now to automate this, we can write a simple script that iterates through all keywords in an account and does this calculation for us.

Account Quality Score Calculation Script

AdWords Scripts

Add a new script from Campaigns > Bulk Operations > Scripts in your AdWords account.


In the new script, replace all the sample code with the code below:

function main() {

var totalImpressionsAnalyzed = 0;

var totalQualityScoreAnalyzed = 0;

var keywordIterator = AdWordsApp.keywords()

.withCondition("Status = ENABLED")

.withCondition("CampaignName CONTAINS_IGNORE_CASE " + "Insert Your Campaign Name Here")

.withCondition("CampaignStatus = ENABLED")

.withCondition("AdGroupStatus = ENABLED")





while (keywordIterator.hasNext()) {

var keyword =;

var qualityScore = keyword.getQualityScore();

var keywordStats = keyword.getStatsFor("LAST_30_DAYS");

var impressions = keywordStats.getImpressions();

var qualityScoreContribution = qualityScore * impressions;

totalQualityScoreAnalyzed = totalQualityScoreAnalyzed + qualityScoreContribution;

totalImpressionsAnalyzed = totalImpressionsAnalyzed + impressions;


var accountQualityScore = totalQualityScoreAnalyzed / totalImpressionsAnalyzed;

Logger.log("QS: " + accountQualityScore);


You can simply copy and paste this code into a new script, authorize it and then preview it. The only thing you should modify is to replace “Insert Your Campaign Name Here” with the part of your campaign names that indicates it’s a search network campaign.

Because ads that run on the Google Display Network and on mobile devices have their own separate QS, you want to process only data from keywords that are in campaigns targeting search to get an accurate result.

Get The Latest Data Automatically Every Day

While this script automates the calculations you could otherwise do in a spreadsheet, you don’t want to have to run this script manually every day, so let’s set it up to run automatically every day.

Schedule AdWords Script


3 Ways To Maintain Your Tracking History

While it’s helpful to know what your account QS is, it’s most useful when you put it into the context of changes you’re making to your account. Knowing that your account QS is a 4 tells you that you need to start optimizing. Knowing that your QS went from a 4 to a 5 tells you you’re doing something right.

So let’s get the QS out of the script and into a place where you can track it.

Here are three ways to extend the script by sending the QS to somewhere useful for you. You can simply add the lines of code for the technique you want to implement just before the final ‘}’.

1.  Send It By Email

The simplest way to get the QS out of your account is to deliver it to your inbox every day.


var recipient = ","; var subject = "Account Quality Score"; var body = "Account Quality Score:\n\n" + accountQualityScore; MailApp.sendEmail(recipient, subject, body);


2.  Add It To A Spreadsheet

An easy way to get the historical perspective is to add the Quality Score and the date to a spreadsheet every day.

var date = new Date(); var spreadsheetUrl = "Insert Your Google Spreadsheet URL Here And Make Sure Your AdWords Login Has Edit Privileges For This Spreadsheet"; var qualityScoreSheet = SpreadsheetApp.openByUrl(spreadsheetUrl).getActiveSheet(); qualityScoreSheet.appendRow([date, accountQualityScore]);


Now, when you make significant changes to your account, you could add an annotation to the spreadsheet on the date when the change was made. For example, when you add a big batch of keywords, put a note along the lines of “added new keywords <url to list>.”

This annotation will be useful, as described further below, when we turn this spreadsheet into a chart for a dashboard.

Account Quality Score in a Google Spreadsheet

Add annotations next to each date so you can track how it impacts Quality Score


3. Send It To An API

If you want to send the QS into your own database, that can be done in a single line of code, but you do need to have your own API for accepting this type of data. A simple API is just a URL that you can call with some variables that contain the data.

My own API call looks like this. You’d replace the part with my URL with your own URL:


var response = UrlFetchApp.fetch("" + accountQualityScore);


Charting Quality Score Progress

When you put the QS into a Google spreadsheet every day, you can easily turn that into a chart and even embed that chart into your own custom dashboard. If you want to see QS along with a few other metrics from your AdWords account, my friend Nick Mihailovski from Google Analytics shared a great script to pull data from Analytics into a Google spreadsheet.

Annotated Quality Score Tracker

Monitor how changes to your AdWords account impact your account-level Quality Score.

If your AdWords and Analytics accounts are linked (as they should be for more advanced remarketing capabilities), you can use this script to make custom AdWords charts that combine data from your account with data you calculate yourself like Quality Score.

Opinions expressed in the article are those of the guest author and not necessarily Search Engine Land.

Related Topics: Channel: SEM | Enterprise SEM | Google: AdWords


About The Author: is the founder and Chief Marketing Technologist of Top Tier Marketing, an online marketing agency specializing in AdWords. He is also the Cofounder of Optmyzr, an AdWords tool company that makes account management more efficient. Prior to forming Top Tier, Vallaeys spent 10 years building AdWords and teaching advertisers how to get the most out of it as the Google AdWords Evangelist.

Connect with the author via: Email | Twitter | Google+ | LinkedIn


Get all the top search stories emailed daily!  


Other ways to share:

Read before commenting! We welcome constructive comments and allow any that meet our common sense criteria. This means being respectful and polite to others. It means providing helpful information that contributes to a story or discussion. It means leaving links only that substantially add further to a discussion. Comments using foul language, being disrespectful to others or otherwise violating what we believe are common sense standards of discussion will be deleted. Comments may also be removed if they are posted from anonymous accounts. You can read more about our comments policy here.
  • Ryan Garrow


  • virginia

    great article, but have you ever tried to get a good quality score for an SEO company using Ad Words?! It aint gona happen…. Quality score always starts off well for perhaps a month and then down it goes. I understand their philosophy but it really is a bit mean.

  • Bret

    When I follow these instructions:

    “You can simply copy and paste this code into a new script, authorize it and then preview it. The only thing you should modify is to replace “Insert Your Campaign Name Here” with the part of your campaign names that indicates it’s a search network campaign.”

    I get the following error:

    “Parsing error. Please check your selector. (line 7)”

    I’m supposed to just replace “Insert Your Campaign Name” with the name of an active ad campaign; no?!??!

    … I’d really like to get this script going. It’s a GREAT idea.

  • Edgar M.

    Ten Scores have a good presentation on how to improve QS, you might also check out at

  • Ava Naves

    Great article, but I’m getting the same error on line 7 as Bret: “Parsing error. Please check your selector”.

    In my case, I’d like to check the QS for a campaign that is currently paused. If I change the following lines to:

    .withCondition(“Status = PAUSED”)

    .withCondition(“CampaignStatus = ENABLED”)

    .withCondition(“AdGroupStatus = ENABLED”)

    … will the script work? I have already changed the campaign name to match my client’s.

    Thank you so much for such a comprehensive and generous post!

  • Greenville Dentist

    FIX FOR ERRORS: I got the same errors everyone else was getting. I tried on a different campaign that contained no spaces or special characters and it worked. So I renamed my other campaign to a single word, no spaces and now it works with no errors.

    Thanks for the script – never used one before.

  • Tom Holder

    Brilliant article.

    I’ve read around the subject area with some interest in the past, but didn’t know how to go about writing the script.

    The main script worked perfectly for me, however I’m having trouble when trying to incorporate the ‘Add it to a spreadsheet’ script. I get the following error…

    ReferenceError: “accountQualityScore” is not defined. (line 51)

    Can anyone help me with a fix for this?

    Thanks in advance.

  • Greenville Dentist

    Tom – had the same problem. The extra code has to go before the last (or next to last) close bracket }. Move it up and try that.

  • Tom Holder

    Ideal, looks to have worked fine.

    Thanks for the reply.

  • Justin Lugbill

    When I paste the code in, I am getting a parsing error on line 7. Any tips? Also, if you want to get the weighted QS segmented by campaign, can you do that, or do you just have to do multiple scripts?

  • Greenville Dentist

    See other comments below. Basically, try a campaign name with no spaces or special characters.

  • Frederick Vallaeys

    Thanks to Greenville Dentist for helping with all the troubleshooting!

    You can indeed remove that entire line and then it will analyze EVERY campaign in your account. That runs the risk of including Display campaigns though so I prefer to keep this line. If you add single quotes around the campaign name or you include just a single word, it should work.

  • Justin Lugbill

    Is there any way to get the data into a specific spreadsheet tab? When I use the tab specific URL, it still is input into the first tab of the spreadsheet.

  • Chris

    Great article Fred. Tracking QS was a problem I desperately needed a solution to a few years ago.

    That’s why I created

    Within 30 seconds of signing up, it will track for you:

    - Account QS
    - Campaigns QS
    - Ad Groups QS
    - Keywords QS

    Weighed by impressions. No hassle with scripts or anything.

    You can then plot the QS evolution against every other other metrics such as CPC, CTR, Costs, First Page Bids, etc…

    It even evaluates how much in terms of $$$ you’re being penalized with low QS and how much of a discount you’re getting with high QS.

    It also shows you were to start optimizing, and we’re bringing in recommendations for advertisers who need guidance in optimizing QS.

    Our users love it!

    Anyways, that’s enough for the pitch…

    It’s not perfect yet imo, but woud love your feedback on how we can improve it, ping me at chris(at) if interested. Anybody reading this can send me a quick email if they want to take it for a spin.

    Or just sign up at:

    Did I mention it only take about 30 seconds to set up?

  • sheila219

    up to I saw the check for $8910, I didn’t believe …that…my friends brother woz like truly receiving money part-time on-line.. there friends cousin started doing this for less than 14 months and as of now cleard the debts on their place and purchased a new Acura. I went here, jump15.comCHECK IT OUT

  • Justin Lugbill

    I was able to install this for one client. However, when I copy and paste (changing the campaign name), I now get a NaN response. I have tried this for multiple campaigns, and still get the same result. What I can’t figure out is, why did it work the first time, and not now. Is anyone else having problems?

  • David Kinney

    great article and code! However, I’m having trouble running this script for multiple (but not ALL) campaigns at once. How do I add more than one campaign name into the “Insert Your Campaign Name” field?

  • Joyce

    Great post! I can’t code but got this working, i wonder, how ever, how i could track several campaigns in 1 spreadsheet? Like have: date, campaign 1, campaign 2, campaign3 in the first line. Making a seperate spreadsheet for my all my campaigns is a bit much and i’d like to see it by campaign, not by account. Ive tried to add more campaign names with + but its not having it, neither do i know how to get the data for the next campaign in line into column C instead of dumping it on the first empty line in column A and B. Could anyone explain this? Again, great post! i finally dared to touch the script function :)

  • Russell Savage

    One thing to keep in mind that according to the AdWords Scripts API Limits ( ), a single iterator can return at most 50000 elements. That means that the line .withLimit(100000) doesn’t really do too much. This script will only process the top 50000 keywords in an account ordered by impressions.

  • Joel Chudleigh

    Another incredible article Frederick – thanks

    Got the script working fine but struggling with the spreadsheet bit. i added in the code

    var date = new Date(); var spreadsheetUrl = “spreadsheet name here”; var qualityScoreSheet = SpreadsheetApp.openByUrl(spreadsheetUrl).getActiveSheet(); qualityScoreSheet.appendRow([date, accountQualityScore]);

    before the closing } but I get an error message.

    “Invalid argument: url (line 46)”

    Line 46 contains the above code that has the spreadsheet detail in it.

    Any help that you can offer would be greatly appreciated as unless I can get this into a spreadsheet then it will not be so actionable.

    Finally – is this script for just one campaign or for the whole account?

    The post talks about account level QS but then in the code for the script you instructed us to enter a specific campaign name. Is it the QS for that campaign or the whole account?

    If it is just for that campaign then how do we get it for the whole account? Ideally I would like to see the data in a spreadsheet by campaign with a total account level at the bottom.

    Don’t ask for much do I…

  • Robert Chapman

    I can get the script working….but now I’m wondering what do I need to do to actually improve the QS across the account. Any tips appreciated!

  • Mark Churchill

    First a big thankyou to Frederick, this is a metric I really want to track

    Just one Q: Am I right in thinking the effect of setting this up as described above is that you’d get a *daily* email showing a calculation based on the *last 30 days* each time?

  • Trevor Fox

    Thanks of the script Frederick,
    Single quotes inside the quotes, eg: “‘My Campaign Name’” solved my parsing error.
    I like spreadsheets, but I LOVE automation.

  • Joel Chudleigh

    In case anyone is interested we found a way to build a script that does the same as above for the account level but also tracks campaign and ad group level quality score. it adds it all to a spreadsheet and emails you a daily report:

  • Ade

    Did you solve the NaN response? I’m getting the same too! Please let me know if you managed to solve it!




Get Our News, Everywhere!

Daily Email:

Follow Search Engine Land on Twitter @sengineland Like Search Engine Land on Facebook Follow Search Engine Land on Google+ Get the Search Engine Land Feed Connect with Search Engine Land on LinkedIn Check out our Tumblr! See us on Pinterest


Click to watch SMX conference video

Join us at one of our SMX or MarTech events:

United States


Australia & China

Learn more about: SMX | MarTech

Free Daily Search News Recap!

SearchCap is a once-per-day newsletter update - sign up below and get the news delivered to you!



Search Engine Land Periodic Table of SEO Success Factors

Get Your Copy
Read The Full SEO Guide