Google Ads IP exclusions
Connecting the Google Ads API, negative IP sync with the 500-per-campaign cap, incident auto-pause and refund-claim evidence.
Updated 2026-09-02
Connect Google Ads#
Under Protect → Rules & Google Ads API enter the developer token, OAuth client id / secret, refresh token, customer id and (optionally) login customer id. Credentials are encrypted with CREDENTIALS_KEY. The connection test lists your active campaigns.
Negative IP sync#
Every blocklist entry is pushed as an IpBlock campaign criterion to each active campaign:
- Google allows 500 IP exclusions per campaign; WhichClick fills the slots with the highest-scoring, most recent entries and rotates expired ones out.
- IPv6 is excluded at the /64 (Google's minimum granularity); IPv4 as single addresses or /24 when a subnet is blocked.
- Sync runs automatically after each new invalid verdict (debounced 60 s) and via
POST /api/protect/syncor the scheduler. IpBlock.googleCriteriarecords the criterion resource name per campaign so removals are exact;lastSyncErrorsurfaces API errors.
Range folding, expiry and campaign scoping#
- Range folding — three or more blocked hosts in one IPv4 /24 become a single CIDR exclusion (
203.0.113.0/24), and the per-host criteria are removed, so the 500-criteria cap per campaign lasts far longer. Runs hourly and from Blocklist → Aggregate now. - Expiry — when a block passes its retention period its Google criteria are removed before the row is deleted; the exclusion list never grows stale.
- Scoping — with Scope auto-exclusions to the attacked campaign on, blocks created during an attack are synced only to that campaign; manual blocks still go everywhere.
Placement exclusions#
With Auto-exclude bad placements on, Display / Video / PMax placements (ValueTrack {placement}) whose clicks were at least the configured invalid share over the last 24 h (default 60 % of ≥ 20 clicks) are added under Blocklist → Excluded placements and synced as negative placement criteria (placement.url, or mobile_application.app_id for mobileapp::… ids). Placements can also be excluded by hand.
Offline conversions#
Turn on Upload verified conversions and enter the numeric id of an Import conversion action. Every hour WhichClick uploads conversions that carry a gclid and belong to a VALID click (uploadClickConversions, value + currency + order id). Conversions on flagged clicks are never sent, so Smart Bidding optimises toward real outcomes. Delivery results appear under Integrations → Google Ads → deliveries.
Budget guard#
Budget guard (Rules → Attack response) cuts the attacked campaign's daily budget by the chosen percentage when an attack incident opens and restores the original amount when the incident is mitigated or resolved. Shared budgets are left untouched.
Incident auto-pause#
When an incident opens on a campaign and auto-pause is enabled, the campaign status is set to PAUSED through the API and a webhook (incident.opened) is sent. Resolving the incident does not automatically resume the campaign — that is a human decision.
{ "type": "incident.opened", "campaign": { "id": "…", "name": "Brand — Search", "externalId": "2098765432" }, "invalidClicks": 63, "windowMinutes": 10, "topIps": ["203.0.113.0/24"], "autoPaused": true }Refund claims#
Google's invalid-activity review requires evidence. Export it with GET /api/protect/export?days=30 (CSV with timestamp, IP, gclid, campaign, ad group, reasons, score) and attach it to the invalid clicks contact form. Keep the exclusion list in sync — reviewers check that you took action.
Microsoft Ads#
The same blocklist can be exported as a Microsoft Ads IP exclusion CSV from Protect → Blocklist; API sync is on the roadmap.