Monitoring MCC + Individual Read-only Email + Telegram Required Google Sheets Available

$ scripts --run disapproved-ads-monitor

Disapproved Ads Monitor

Monitor enabled Search ads for policy issues, receive one concise summary per run, and review the full history in Google Sheets.

The script monitors active ads and sends operational alerts. It does not edit ads, submit appeals, or guarantee uninterrupted detection or delivery.

What this script monitors

  • Reads active ads within active ad groups and active campaigns only — paused and removed entities are excluded.
  • By default monitors only DISAPPROVED approval status. APPROVED_LIMITED can be added explicitly to MONITORED_APPROVAL_STATUSES.
  • Monitors ad_group_ad entries (responsive search ads, expanded text ads, etc.) — not assets or extensions.
  • Tracks policy topics reported for each affected ad when available.
  • Stores state per account using a composite key (adGroupId:adId) in Script Properties — survives re-runs and quota resets.
  • Running the script more than once on the same day does not create duplicate alerts.
  • An unchanged issue receives a REMINDER after the configured number of days.
  • An ad confirmed as APPROVED after a previously flagged status triggers a RECOVERY event.
How Disapproved Ads Monitor works — Google Ads Script checks ad approval status across accounts and delivers policy violation alerts via Email, Telegram, and Google Sheets
Alert delivery flow — Email, Telegram, and Google Sheets report. Demo data.

Alert events

Event Meaning
NEW_ISSUE A monitored policy issue was detected for the first time.
STATUS_CHANGED The ad changed between monitored problem statuses (e.g. DISAPPROVED to APPROVED_LIMITED).
REMINDER The issue remains unchanged and the configured reminder interval has passed.
RECOVERY The previously affected ad is now confirmed as APPROVED.
NO_LONGER_MONITORED The ad is no longer in the active monitored set. This does not confirm approval — it may have been paused or removed.

Notification examples

Sanitized demo data — no real account credentials or client information.

Email — one summary per run

Subject: Google Ads Alert - Disapproved Ads Monitor - Check completed

Environment: STANDALONE

Checked accounts: 1

Events: 2

Errors: 0

Disapproved Ads Monitor

Check completed

Scope: Enabled Search campaigns, ad groups, and ads

Accounts checked: 1

Search campaigns checked: 3

Search ad groups checked: 12

Search ads checked: 48

Disapproved: 2

Approved limited: 0

New issues: 2

Status changed: 0

Reminders: 0

Recovered: 0

No longer monitored: 0

Errors: 0

Policy issues found. See the full report for details.

Full report:
https://docs.google.com/spreadsheets/d/…

Maker Unit: https://maker-unit.com/

One email per run regardless of event count. For per-issue details, open the linked Google Sheets report.

Telegram — one summary per run

⚠️ Disapproved Ads Monitor

Check completed

Scope: Enabled Search campaigns, ad groups, and ads

Accounts checked: 1

Search campaigns checked: 3

Search ad groups checked: 12

Search ads checked: 48

Disapproved: 2

Approved limited: 0

New issues: 2

Status changed: 0

Reminders: 0

Recovered: 0

No longer monitored: 0

Errors: 0

Policy issues found. See the full report for details.

Full report:
https://docs.google.com/spreadsheets/d/…

Telegram is disabled by default. Requires a private bot token and chat ID in your installed copy. Token is redacted in error messages.

Google Sheets — required, 3 sheets

Sheet 1: Current Issues (upserted per ad)

issue_keyrecord_statuscustomer_idaccount_namead_idapproval_statuspolicy_topicsfirst_seenlast_seenresolved_at
123456890:111222333:123456789ACTIVE123-456-7890Demo Store123456789DISAPPROVEDExample Policy2026-07-252026-07-25

Sheet 2: Event History (append-only)

event_timestampevent_typecustomer_idaccount_namead_idprevious_statuscurrent_statuspolicy_topicsfirst_seennext_reminder
2026-07-25NEW_ISSUE123-456-7890Demo Store123456789NONEDISAPPROVEDExample Policy2026-07-252026-08-01

Sheet 3: Run Log (append-only)

run_timestampmodeenvironmentaccounts_checkedads_checkednew_issuesremindersrecoverederrorsemail_resultsheets_result
2026-07-25T09:00:00ZPRODUCTIONSTANDALONE1482000SENTUPDATED

Google Sheets is required. Sheets stores the detailed report — state is kept in Script Properties. TEST_MODE creates sheet headers and one TEST row in Run Log only; no production events or Current Issues are written.

Disapproved Ads Monitor email alert example showing disapproved and limited ads with policy violation details and account summary
Example email alert summary — sanitized demo data, not real account values.

Installation

  1. 1 Open Google Ads → Tools → Bulk actions → Scripts (or MCC Scripts for MCC accounts).
  2. 2 Click New script and paste the complete release artifact.
  3. 3 In the CONFIG block at the top, add your allowed Customer IDs to ACCOUNT_IDS.
  4. 4 Keep MONITORED_APPROVAL_STATUSES as ['DISAPPROVED'] for your first test.
  5. 5 Set EMAIL_RECIPIENTS to one or more recipient email addresses.
  6. 6 Set GOOGLE_SHEETS_SPREADSHEET_ID to the ID of an existing Google Spreadsheet that your authorized Google user can write to. GOOGLE_SHEETS_ENABLED must remain true — the required detailed report cannot be disabled. Set TELEGRAM_ENABLED to false initially.
  7. 7 Set TEST_MODE: true.
  8. 8 Authorize access — Google Ads read access and Google Sheets write access are required for all runs; external HTTP access (UrlFetchApp) is required only when Telegram is enabled.
  9. 9 Run Preview and compare Customer ID, campaign, ad group, ad ID, approval status, and policy topics against Google Ads Policy details.
  10. 10 Verify the [TEST] summary email arrives and the three Google Sheets tabs (Current Issues, Event History, Run Log) are created with correct headers and one TEST row in Run Log. Run Preview again on the same day to confirm no duplicate rows appear.
  11. 11 Test Telegram by setting TELEGRAM_ENABLED: true after the bot token and chat ID are configured in your private installed copy. Verify the run summary message appears.
  12. 12 Set TEST_MODE: false.
  13. 13 Configure a daily schedule (recommended: 09:00 in your account timezone).

CONFIG reference

ACCOUNT_IDS string[]

Allowlist of Google Ads Customer IDs. Required for both MCC and standalone mode. In standalone mode, must include the current account's ID.

MONITORED_APPROVAL_STATUSES string[]

Policy statuses that trigger events. Default: ['DISAPPROVED']. Add 'APPROVED_LIMITED' only when limited-delivery ads should also generate alerts.

REMINDER_INTERVAL_DAYS number

Calendar days to wait before resending an alert for an unchanged issue. Default: 7.

EMAIL_ENABLED boolean

Enables Email notifications. Default: true.

EMAIL_RECIPIENTS string[]

One or more email addresses to receive alerts. Required when EMAIL_ENABLED is true.

TELEGRAM_ENABLED boolean

Enables Telegram notifications. Default: false. Enable only after private credentials are configured and tested.

TELEGRAM_BOT_TOKEN string

Telegram bot token. Set only in your private installed copy — never share or commit this value.

TELEGRAM_CHAT_ID string

Destination Telegram chat or group ID. Set only in your private installed copy.

GOOGLE_SHEETS_ENABLED boolean

Google Sheets logging is required and must remain true. Setting false causes the script to reject the configuration at startup.

GOOGLE_SHEETS_SPREADSHEET_ID string

ID of an existing Google Spreadsheet that the authorized Google user can write to. Required for all runs.

GOOGLE_SHEETS_CURRENT_ISSUES_SHEET_NAME string

Worksheet name for the issue registry. Each active issue is upserted by composite key so there are no duplicate rows. Default: 'Current Issues'.

GOOGLE_SHEETS_EVENT_HISTORY_SHEET_NAME string

Worksheet name for the append-only event history. Every NEW_ISSUE, STATUS_CHANGED, REMINDER, RECOVERY, and NO_LONGER_MONITORED event adds one row. Default: 'Event History'.

GOOGLE_SHEETS_RUN_LOG_SHEET_NAME string

Worksheet name for the append-only run log. One row per script execution with counts, environment, mode, and delivery results. Default: 'Run Log'.

TEST_MODE boolean

Sends alerts with a [TEST] prefix and creates the Google Sheets structure with one TEST row in Run Log, but does not save production state or write event rows to Current Issues or Event History. Default: false. Use true for initial verification only.

BRAND_NAME string

Sender label shown in Email notifications. Default: 'Maker Unit'.

BRAND_URL string

Branding link included at the bottom of Email notifications.

Limitations

  • Only active ads inside active ad groups and active campaigns are included in the snapshot.
  • Assets and extensions are not monitored in version 0.2.0.
  • An ad absent from the active snapshot receives NO_LONGER_MONITORED — not a false RECOVERY. Approval is not assumed.
  • Policy topic details may be absent even when a disapproval status is present — this is a Google Ads API limitation.
  • Large accounts with many ads may approach the Google Ads Scripts execution-time quota.
  • Email and Telegram delivery depend on external services and authorized permissions.
  • Script state is stored in Script Properties of your installed copy and is not shared between copies.
  • The script does not submit policy appeals, edit ads, or make any changes to your Google Ads account.

Script code

disapproved-ads-monitor-v0.2.0.js 1224 lines

Video walkthrough

Video guide coming soon — follow us on Telegram to get notified.

FAQ

Does it work in MCC and individual accounts?

Yes. When run from an MCC, it iterates over child accounts listed in ACCOUNT_IDS and processes each one separately. In standalone mode, the current account's ID must be included in ACCOUNT_IDS.

Does it change, pause, or resubmit ads?

No. The script is entirely read-only in Google Ads. It runs a GAQL query to read ad statuses and policy data, then sends notifications through external channels. No ad data is modified.

Does it monitor assets or extensions?

No. Version 0.2.0 monitors ad_group_ad entries only — responsive search ads, expanded text ads, and similar formats. Asset-level policy monitoring is not included in this version.

What is monitored by default?

Only DISAPPROVED ads. This is the safe default for most accounts. APPROVED_LIMITED is not included unless you explicitly add it to MONITORED_APPROVAL_STATUSES.

Should I enable APPROVED_LIMITED?

Only if limited ad visibility is relevant for your campaigns. APPROVED_LIMITED means the ad is approved but delivery is restricted in some contexts. Many accounts choose to monitor DISAPPROVED only to reduce noise.

What is the difference between RECOVERY and NO_LONGER_MONITORED?

RECOVERY means the ad appeared in the active snapshot with an APPROVED status after previously being flagged. NO_LONGER_MONITORED means the ad was not present in the active snapshot at all — it may have been paused, removed, or stopped serving. Approval is not assumed.

How often are reminders sent?

Once every REMINDER_INTERVAL_DAYS (default: 7) calendar days, as long as the issue remains unchanged. A STATUS_CHANGED or RECOVERY event resets the reminder clock.

Can I use Email without Telegram?

Yes. EMAIL_ENABLED and TELEGRAM_ENABLED are independent switches. You can enable Email only, Telegram only, or both. Telegram requires a private bot token and chat ID configured in your installed copy.

Is Google Sheets required?

Yes. Google Sheets is required in version 0.2.0. Setting GOOGLE_SHEETS_ENABLED to false is rejected by the config validation. The spreadsheet stores three sheets: Current Issues (upserted issue registry), Event History (append-only event log), and Run Log (append-only per-run log). A valid GOOGLE_SHEETS_SPREADSHEET_ID is always required.

What does TEST_MODE do?

TEST_MODE: true sends alerts with a [TEST] prefix, creates the required Google Sheets tabs with correct headers, and appends one TEST row to the Run Log — but does not save production state to Script Properties and does not write event rows to Current Issues or Event History. Use it to verify the full output format before going live.

Why did an alert not arrive?

Check that EMAIL_ENABLED is true and EMAIL_RECIPIENTS contains a valid address. Verify MailApp authorization in Google Ads Scripts. Also check your spam folder. For Telegram, confirm the bot token and chat ID are correct and the bot has access to the chat.

Why is a disapproved ad absent from the results?

The script only includes ads where the ad itself, its ad group, and its campaign are all in ENABLED status. If any of those is paused or removed, the ad is excluded from the snapshot.

What permissions are required?

Google Ads read access is required for all runs. MailApp authorization is required for Email. External URL fetch (UrlFetchApp) is required for Telegram. SpreadsheetApp write access is required for Google Sheets.

How do I verify that the installed version is current?

Check the version comment or CONFIG block in the script you installed against the version shown on this page. The download filename also includes the version number (e.g. disapproved-ads-monitor-v0.2.0.js).

Get notified when new scripts drop

No spam. Just a short email when a new script is published.

No spam. Unsubscribe any time.