Skip to content

Google Ads Negative Keyword Conflict Checker Script (GAQL)

Automated Google Ads script that cross-references campaign, ad group and shared negative lists against active positive keywords to flag silent blocking.

By Gordon Geraghty·MIT Licence·Updated: 21 August 2026·BEGINNER·GitHub Mirror ↗

How Negative Keyword Collisions Waste High-Intent Budget

Shared negative lists and campaign-level broad negatives frequently block exact and phrase match positive keywords without triggering any visible alert in the Google Ads user interface. This script cross-checks all serving campaigns hourly to ensure active revenue-generating keywords remain unobstructed.

Implementation Code & Script

GAQL Negative Keyword Conflict ScriptNegativeKeywordConflictChecker.jsjavascript

Copy and paste into Google Ads Scripts editor. Filters to serving campaigns and sends alert emails.

/**
 * Google Ads Negative Keyword Conflict Checker (GAQL)
 * Author: Gordon Geraghty - Head of Performance, Empire Amplify
 * Licence: MIT
 * Filter: campaign.status = "ENABLED" AND campaign.serving_status = "SERVING"
 */

const CONFIG = {
  EMAIL_RECIPIENT: 'gordon@empireamplify.com.au',
  SPREADSHEET_URL: '', // Optional: Paste a Google Sheet URL to log findings
};

function main() {
  Logger.log('Starting Negative Keyword Conflict Audit...');
  
  // 1. Fetch all active positive keywords in serving campaigns
  const positiveQuery =
    'SELECT campaign.id, campaign.name, ad_group.id, ad_group.name, ' +
    'ad_group_criterion.keyword.text, ad_group_criterion.keyword.match_type ' +
    'FROM keyword_view ' +
    'WHERE campaign.status = "ENABLED" ' +
    'AND campaign.serving_status = "SERVING" ' +
    'AND ad_group.status = "ENABLED" ' +
    'AND ad_group_criterion.status = "ENABLED"';

  const positiveRows = AdsApp.search(positiveQuery);
  const positiveKeywords = [];
  
  while (positiveRows.hasNext()) {
    const row = positiveRows.next();
    positiveKeywords.push({
      campaignName: row.campaign.name,
      adGroupName: row.adGroup.name,
      text: row.adGroupCriterion.keyword.text.toLowerCase().trim(),
      matchType: row.adGroupCriterion.keyword.matchType,
    });
  }
  
  Logger.log('Found ' + positiveKeywords.length + ' active positive keywords.');

  // 2. Fetch all campaign and ad group negative keywords
  const negativeQuery =
    'SELECT campaign.name, ad_group.name, ' +
    'campaign_criterion.keyword.text, campaign_criterion.keyword.match_type, ' +
    'campaign_criterion.negative ' +
    'FROM campaign_criterion ' +
    'WHERE campaign.status = "ENABLED" ' +
    'AND campaign.serving_status = "SERVING" ' +
    'AND campaign_criterion.negative = TRUE';

  const negativeRows = AdsApp.search(negativeQuery);
  const conflicts = [];

  while (negativeRows.hasNext()) {
    const neg = negativeRows.next();
    const negText = neg.campaignCriterion?.keyword?.text?.toLowerCase().trim();
    if (!negText) continue;

    positiveKeywords.forEach(function(pos) {
      if (pos.campaignName === neg.campaign.name && pos.text.indexOf(negText) !== -1) {
        conflicts.push({
          campaign: pos.campaignName,
          adGroup: pos.adGroupName,
          positiveKeyword: pos.text,
          negativeKeyword: negText,
        });
      }
    });
  }

  Logger.log('Audit complete. Conflicts detected: ' + conflicts.length);

  if (conflicts.length > 0 && CONFIG.EMAIL_RECIPIENT) {
    let body = 'Google Ads Negative Keyword Conflicts Detected:\n\n';
    conflicts.forEach(function(c) {
      body += 'Campaign: ' + c.campaign + ' | Ad Group: ' + c.adGroup + '\n';
      body += 'Positive: "' + c.positiveKeyword + '" BLOCKED BY Negative: "' + c.negativeKeyword + '"\n\n';
    });
    MailApp.sendEmail(CONFIG.EMAIL_RECIPIENT, 'Google Ads Conflict Alert: ' + conflicts.length + ' blocked keywords', body);
  }
}

How to cite and attribute this tool

MIT Licence

This resource is free, open and un-gated under the MIT Open Source Licence. You are encouraged to use, integrate and cite it with attribution:

Geraghty, G. (2026). Google Ads Negative Keyword Conflict Checker Script (GAQL). Gordon Geraghty Resources Hub. https://gordongeraghty.com/resources/performance-media/negative-keyword-conflict-checker
BibTeX Format
@misc{geraghty_negative_keyword_conflict_checker,
  author = {Geraghty, Gordon},
  title = {Google Ads Negative Keyword Conflict Checker Script (GAQL)},
  year = {2026},
  url = {https://gordongeraghty.com/resources/performance-media/negative-keyword-conflict-checker},
  note = {Head of Performance, Empire Amplify}
}

Changelog & Version History

  • v1.0.0Initial release using GAQL through AdsApp.search with serving campaign status filtering.