If you manage Google Ads accounts that mix Search, Shopping and Performance Max, reviewing search terms usually means jumping between reports. Search and Shopping terms sit at ad-group level. Performance Max terms come from a separate view at campaign level. Then you export both, stitch them together in a spreadsheet and sort by cost.
I got tired of doing that by hand, so I wrote a small Google Ads script that does it in one run. It's free, open source (MIT) and read-only: it never adds negatives, changes bids or touches settings. It just gives you a cleaner list to make decisions from.
Repo: github.com/hustlemarketers-art/google-ads-scripts (the file is 02-search-term-review.js).
What the script does
- Pulls Search and Shopping search terms with ad group context.
- Pulls Performance Max search terms at campaign level.
- Merges both lists and sorts them by cost, highest first.
- Calculates cost, clicks, conversions, conversion value, CPA and value ROAS for every term.
- Flags terms for review:
-
REVIEW_COST_WITHOUT_RECORDED_CONVERSIONS: the term spent past your threshold with no recorded conversions. -
REVIEW_CPA_ABOVE_ENTERED_TARGET: CPA is above the target you set (only if you set one). -
REVIEW_ROAS_BELOW_ENTERED_TARGET: value ROAS is below the target you set (only if you set one).
-
- Writes the top rows to the Logs, and optionally the full report as a CSV in your own Google Drive.
Install it in 5 minutes
- In Google Ads, open Tools > Bulk actions > Scripts and create a new script.
- Paste the whole of
02-search-term-review.js. - Review the
CONFIGblock (below). - Authorize the script, click Preview and read the Logs.
- If the output looks right, set
OUTPUT_TO_DRIVE: trueand run it normally to get the full CSV. Drive writes are skipped in Preview, so Preview never creates files.
The script runs in one account at a time. It is not a manager-account (MCC) script.
The settings that matter
const CONFIG = {
DATE_RANGE: 'LAST_30_DAYS',
MIN_COST: 100, // Account currency
MIN_CLICKS: 30,
MIN_CONVERSIONS: 5,
TARGET_CPA: 0, // 0 turns this rule off
TARGET_ROAS: 0, // e.g. 4 means 4x; 0 turns it off
MAX_ROWS: 20000,
LOG_ROWS: 20,
OUTPUT_TO_DRIVE: false,
INCLUDE_PMAX: true
};
-
MIN_COSTandMIN_CLICKSstop the "no conversions" flag from firing on terms that haven't had a fair chance yet. Set them in your account's currency and to your typical CPA, not a generic number. -
TARGET_CPAandTARGET_ROASare off by default because every account's economics are different. If you use ROAS, work out your break-even ROAS first. A 4x ROAS can still lose money on thin margins. -
INCLUDE_PMAX: if your Scripts runtime doesn't support the campaign-level search term view, the script stops with a clear message. Set this tofalseto get the Search and Shopping report on its own.
The two GAQL queries
Search and Shopping terms come from search_term_view:
SELECT campaign.id, campaign.name, ad_group.id, ad_group.name,
search_term_view.search_term,
metrics.cost_micros, metrics.clicks, metrics.impressions,
metrics.conversions, metrics.conversions_value
FROM search_term_view
WHERE campaign.advertising_channel_type IN ('SEARCH', 'SHOPPING')
AND campaign.status != 'REMOVED'
AND metrics.cost_micros > 0
AND segments.date DURING LAST_30_DAYS
ORDER BY metrics.cost_micros DESC
Performance Max terms come from campaign_search_term_view, because search_term_view doesn't include PMax:
SELECT campaign.id, campaign.name,
campaign_search_term_view.search_term,
metrics.cost_micros, metrics.clicks, metrics.impressions,
metrics.conversions, metrics.conversions_value
FROM campaign_search_term_view
WHERE campaign.advertising_channel_type = 'PERFORMANCE_MAX'
AND campaign.status != 'REMOVED'
AND metrics.cost_micros > 0
AND segments.date DURING LAST_30_DAYS
ORDER BY metrics.cost_micros DESC
The script turns cost_micros into normal currency, works out CPA and ROAS, and only divides when the denominator is above zero. A term with no conversions shows a blank CPA, not a misleading zero.
How I read the report
- Start at the top. The list is sorted by cost, so the first 20 rows are usually where most of the wasted spend is.
- Treat flags as questions, not verdicts. A flagged term might be early in a long sales cycle or tracked under a different conversion action. Check conversion lag and attribution before you act.
- Decide the fix yourself. For Search, that might mean a negative keyword or a tighter match type. For PMax, it might mean an account-level negative, brand exclusions or better asset-group signals. The script deliberately leaves these decisions to you.
- Remember what's missing. Google only shows some search terms, so the report isn't a complete record of every search. PMax terms are at campaign level only.
Tested before you trust it
The repo has 13 automated tests that run every script against mocked Google Ads responses on every push. They cover micros conversion, review flags, merging Search and PMax terms, CSV escaping (including spreadsheet formula injection) and the Preview export guard. They can't replace a Preview run in your own account, so always do that first.
The other scripts in the repo
-
01-campaign-performance-audit.js: campaign-level cost, conversions, CPA and ROAS with the same review flags. -
03-shopping-product-performance.js: item-level Shopping and PMax product performance. -
04-account-budget-pacing.js: calendar-month pacing against your media budget. -
05-ad-final-url-checker.js: HTTP status and redirects for every final URL in enabled ads.
If you try it, I'd like to hear what you'd add next. Issues and pull requests are welcome on GitHub.
I'm Ishant Sharma, a Google Ads and SEO specialist since 2013 and founder of Hustle Marketers. I share the tools I use in client work at github.com/hustlemarketers-art.
Top comments (0)