Product Campaign Overlap Analyzer
Finds products that got traffic in two or more Shopping / Performance Max campaigns, verifies those campaigns can actually reach the same users (language, device, audience and geo targeting intersect), compares ROAS or CPA per campaign and tells you which campaign should keep each product and which should exclude it. Report only — nothing is changed in the account.
by Dmytro Tonkikh·chiliad.io/marketplace/product-campaign-overlap-analyzer
Overview
Shopping and PMax campaigns that both carry the same product bid against each other, and Google picks the winner by Ad Rank rather than by your ROAS. The script pulls product x campaign performance from shopping_performance_view for the lookback window, keeps only products present in 2+ campaigns, and picks the best campaign by ROAS (or CPA). Before recommending an exclusion it loads each campaign's language, device, location, proximity and audience targeting (campaign and ad-group level, targeting vs observation) and walks the geo hierarchy, so campaigns that can never compete for the same user come back as NO_OVERLAP instead of EXCLUDE. Two sheet tabs are written: a detail tab (one row per product x campaign with verdict KEEP / EXCLUDE / SIMILAR / LOW_DATA / NO_CONVERSIONS / NO_OVERLAP / REVIEW_TARGETING) and a summary tab (one row per overlapping product with the winner, the campaigns to exclude from, and the cost spent in losing campaigns). An optional email fires only when at least one EXCLUDE was produced.
Setup
- 1Open Google Ads → Tools → Bulk Actions → Scripts and create a new script.
- 2Paste the code and authorise Google Ads, Sheets and Mail when asked.
- 3Leave SPREADSHEET_URL empty for the first run: the script creates a spreadsheet and prints its URL in the logs. Paste that URL into SPREADSHEET_URL so every run reuses it.
- 4Choose PRIMARY_METRIC ('ROAS' for e-commerce revenue, 'CPA' for lead-style conversions) and adjust LOOKBACK_DAYS, MIN_CLICKS and MIN_IMPROVEMENT_PCT to your traffic volume.
- 5Optionally narrow the scope with CAMPAIGN_NAME_CONTAINS, set INCLUDE_PMAX = false to compare Standard Shopping only, and add EMAIL_RECIPIENTS for alerts.
- 6Preview once to check the sheet, then schedule weekly.
- 7Act on the summary tab: exclude the product from the losing campaign's listing groups (or via a custom label) — the script never changes the account.
Configuration Variables
| Variable | Default |
|---|---|
SPREADSHEET_URL | (empty) |
OUTPUT_SHEET | product_overlap |
SUMMARY_SHEET | overlap_summary |
PRIMARY_METRIC | ROAS |
LOOKBACK_DAYS |
Expected Output
Analysing last 30 days (2026-08-17 to 2026-09-15). 1284 product(s) with traffic, 96 running in 2+ campaigns, 41 EXCLUDE recommendation(s). Cost in losing campaigns: 2318.4 EUR. Report: https://docs.google.com/spreadsheets/d/1AbC.../edit Alert email sent to: ppc@example.com
Notes
Report only — nothing is changed in the account. The winner is chosen only among campaigns with conversions; products with no converting campaign are NO_CONVERSIONS. Targeting checks cover languages, devices switched off via bid modifier 0, positive and negative locations (including parent geos), and campaign- and ad-group-level audiences in targeting mode; radius and location-group targets cannot be compared and yield REVIEW_TARGETING. PMax rows sometimes arrive without product segments and are skipped. Today is excluded from the window because its data is incomplete. Runs at single-account level; for an MCC assign it to the child accounts.