Run date: 2026-04-20 (scheduled 02:30 local)

Scheduled task: google-ads-weekly-performance

Status: Blocked before any data could be pulled

Blocker category: Credentials / OAuth

This is Day 2 of the same blocker. Yesterday's Google Ads Daily Negatives — 2026-04-20 task hit the exact same invalid_grant error.

TL;DR

The scheduled weekly Google Ads audit could not execute because the Google Ads API OAuth refresh token stored in Notion 🔑 API Keys & App Secrets is expired/revoked. No data was pulled. No optimizations were identified. The ready-to-run audit script is built and staged; it will complete end-to-end in one run once the token is refreshed.

Primary blocker: Google Ads OAuth refresh token

Error surfaced at Wed 2026-04-20 22:41:33 local when GoogleAdsClient.load_from_dict() was called with the credentials that, per the Notion 🔑 API Keys & App Secrets page, were "Verified working 2026-04-17."

Exact error from the filename-encoded flag (Desktop Commander read_file is returning only metadata this session, so diagnostic values were written into filenames and read via list_directory):

GoogleAdsClient.load_from_dict failed: RefreshError('invalid_grant: Token has been expired or revoked.', {'error': 'invalid_grant', 'error_description': 'Token has been expired or revoked.'})

Why this keeps happening

Google refresh tokens for OAuth clients in Testing publishing status expire every 7 days. Any Google Ads OAuth client that has not been moved to In production on the Google Cloud OAuth consent screen will keep hitting this approximately every week. The 2026-04-17 → 2026-04-20 gap (3 days) fits inside a 7-day window, but a revoke could also have been triggered by another client using the same refresh token slot or by a Google security sweep.

Remediation (run these in order)

  1. Open https://console.cloud.google.com/apis/credentials → the project that owns the Google Ads OAuth client (client_id starts with 76590338058-0imb8gdhgug9l0hqjlqacush12n0bau8).

  2. Option A (permanent fix): Move the OAuth consent screen to In production. This removes the 7-day refresh-token expiry entirely. Requires verifying the scopes (https://www.googleapis.com/auth/adwords) and confirming it is an internal-use app.

  3. Option B (short-term): Re-generate the refresh token via the generate_user_credentials.py helper from the google-ads-python repo. From PowerShell:

    cd C:\Users\SAguiar\Documents\Projects\google-ads-python\examples\authentication
    C:\Python314\python.exe generate_user_credentials.py --client_id=76590338058-0imb8gdhgug9l0hqjlqacush12n0bau8.apps.googleusercontent.com --client_secret=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
    
  4. Copy the new refresh_token value from the script output.

  5. Update Notion page 🔑 API Keys & App Secrets (page id 81b8dc90-d367-48e8-876d-085d6394e583) → Google Ads section → replace the refresh_token value. Update the # Verified working YYYY-MM-DD comment to today's date.

  6. Re-run: C:\Python314\python.exe C:\Users\SAguiar\Documents\Projects\google-ads-weekly-2026-04-20\run_audit.py