=== ClickSheriff – Google Ads Traffic Integrity Monitor ===
Contributors: seoport
Tags: google ads, ppc, traffic quality, bot detection, analytics
Requires at least: 5.8
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 4.2.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

See whether your Google Ads traffic is measured correctly, and review repeated visit patterns before spending money on exclusions.

== Description ==

ClickSheriff answers two questions about the traffic your Google Ads budget buys.

**First: is it being measured at all?** Every dashboard leads with a measurement state — *setup required*, *learning*, *monitoring*, or *action needed*. This matters more than it sounds. "No suspicious activity" and "the tracking never worked" produce identical empty screens in most tools, and they are opposite situations. ClickSheriff will not show you a clean bill of health it cannot back up.

**Second: does anything repeat?** Visits arriving from a Google Ads click are scored by independent signals — where the request came from, how it behaved, whether the same address keeps returning through a paid ad. A pattern is only called *strong* when at least two independent *observations* agree, or when an invisible-link trap was followed. Several signals can describe one observation — two counts of the same network are one, five browser quirks are one — and those do not corroborate each other. Everything weaker is shown, labelled honestly, and left alone.

= What it does not do =

These limits are the product, not caveats hidden in a FAQ:

* **It never blocks, hides or redirects a visitor.** Your phone number and call-to-action are shown to everyone, always. Earlier versions could hide them from "flagged" visitors; that judged people by network origin, which reaches real customers on corporate VPNs and hosted browsers. It is disabled in code and cannot be switched back on from the interface.
* **It never touches your Google Ads account.** No API key, no OAuth, no access granted to anyone. If you choose to use the optional Google Ads Script, it runs inside your own account and can only apply addresses you approved by hand.
* **It does not promise a refund.** Google decides invalid-activity credits. ClickSheriff can hand you the per-click data to ask with, and nothing more.
* **It does not claim to find all invalid traffic.** Google filters a large share of it before you are billed. What ClickSheriff measures is what survived that filter and reached your site — which is why its numbers are smaller than the ones advertised elsewhere. Smaller and checkable.
* **It covers Google Search.** Microsoft/Bing clicks are recorded for completeness but are explicitly not analysed or claimed in this version. Meta, TikTok and Performance Max are not covered at all.

= How a pattern is judged =

* A network origin on its own — a datacenter address, a VPN, a missing click id — can never produce a finding. Something the visitor *did* has to corroborate it.
* Two independent *observations* must agree before anything is called strong and offered for review — counted by what was seen, not by how many signals computed it.
* A visitor who converted is cleared automatically, and the conversion is shown as counter-evidence on the finding.
* Real users on iCloud Private Relay, Cloudflare WARP, Google proxies and mobile carrier NAT are recognised as such, not as "datacenter traffic".
* Your own addresses, once configured, are never analysed and can never be suggested for exclusion.
* Search engines and CDNs are allowlisted and never assessed.
* Every assessment stores the ruleset version, the score and the exact signals behind it. Nothing is a black box.

= Money =

The dashboard shows **potential exposure**, never "money saved" or "money lost". It is matched clicks multiplied by your average CPC — an upper bound on what those clicks could have cost, on the assumption Google billed for all of them, which it may not have. With the optional Google Ads Script the figure is replaced by the real cost from your own billing data.

= Free includes =

* The full detection engine and every signal
* The measurement-health verdict and the setup checklist
* Traffic overview, risk overview and explained findings, 30 days of history
* Findings with masked addresses and the full reasoning behind each one
* A monthly traffic integrity report on screen
* The weekly summary email and a first-catch notification
* Configurable retention, GDPR disclosure text, no external calls, no account
* The recurring-devices list: one browser profile arriving through your ads on many days from many networks, with no address shown and no exclusion suggested

= Pro adds =

* Full addresses instead of masked ones
* 90 days of history in the dashboard
* The evidence card behind every finding — including what argues against it
* CSV exports: findings, evidence for Google's Click Quality Form, and the approved exclusion list
* Email and Telegram alerts on strong patterns only
* The exclusion review queue with an append-only audit trail of every decision
* Verified costs from your own Google Ads data instead of an estimate
* The monthly report as a downloadable file

A licence gates depth, never measurement. If Pro lapses, tracking, scoring and your stored data continue untouched — only the Pro views lock, and everything returns the moment a licence is added.

== Installation ==

1. Install and activate the plugin.
2. Open **ClickSheriff → Setup**. It runs six checks against your own data and tells you what is missing.
3. Turn on auto-tagging in Google Ads (Admin → Account settings → Auto-tagging) so visits can be matched to billed clicks.
4. Add your own office and mobile addresses in Settings, so checking your own ad never looks like a finding.
5. Set your average CPC if you want exposure expressed in money.
6. Wait about a week. Until roughly 30 visits over 7 days the dashboard says *Learning* and asks you to do nothing.

== Frequently Asked Questions ==

= Does it block bad clicks? =
No. It measures and explains; you decide. Nothing is hidden from any visitor and no traffic is turned away.

= Will it get my money back from Google? =
It cannot promise that. Google runs its own invalid-traffic filtering and decides credits itself. Pro can export a per-click evidence CSV shaped for Google's Click Quality Form, which is the channel to ask through. Whether Google agrees is up to Google.

= Why are the numbers smaller than other tools report? =
Because most of what those tools count has already been filtered by Google before you were billed, or was never billed at all — link-preview bots, crawlers, re-opened ad URLs. ClickSheriff keeps that activity in a separate "never billed" ledger and out of every money figure, because counting it would flatter the dashboard at your expense.

= Does it need access to my Google Ads account? =
No. Nothing is connected. The optional script runs inside your own account, under your own login, and only applies addresses you approved.

= Can it add IP exclusions automatically? =
Only if you switch that on, and then only for addresses you approved one at a time in the review queue. Out of the box, and after every update, the feed publishes nothing. Revoking an approval removes the exclusion again on the script's next run.

= Will it flag my real customers? =
The engine is built around not doing that: origin alone can never convict, two independent observations are required for a strong assessment, converting visitors are cleared, privacy relays and carrier NAT are recognised, and your own addresses are excluded outright.

= Does it make external calls? =
Detection never does. Every dataset the engine uses — the hosting and privacy-relay ranges, the bot user-agent list — is bundled with the plugin and works offline, so no visit is ever looked up anywhere.

There is exactly one outbound request, and only if you switch it on: **Telegram alerts** (Pro). If you enter a bot token and a chat id in Settings, then each time a visit matches a strong pattern the plugin sends that finding — the visitor's IP address, the score and the reason tokens behind it, plus your site's hostname and a link to your dashboard — to `api.telegram.org`, which delivers it to you. It is sent to Telegram Messenger Inc.; their terms are at https://telegram.org/tos and their privacy policy at https://telegram.org/privacy. Nothing is sent for visits that do not match, and nothing is sent at all while the fields are empty, which is how the plugin ships. The suggested privacy-policy text under Settings → Privacy changes to disclose this as soon as you enable it.

= What personal data does it store? =
For visitors arriving from an ad: the IP address, a non-identifying browser fingerprint, the user agent, the landing URL and basic on-page behaviour. Only to assess traffic quality, deleted automatically after your retention window (90 days by default). Suggested privacy-policy text is provided under Settings → Privacy.

== Changelog ==

= 4.2.0 =
* **Removed: the browser-profile recurrence branch, and the verdicts it already produced.** It scored a visitor for arriving by ad on several separate days, on the premise that customers do not do that. On the account this was measured against, devices returning on 4+ days bought in 25.0% of cases against 1.7% for one-off devices, and 14 of those 16 devices carried the flag — including all four that bought. Every `suspicious` verdict that account displayed came from this branch. The profile could not have supported it either: it is a hash of user agent, screen size, colour depth, timezone, language and core count, so it names a browser model rather than a device.
* **Stored verdicts that rested on it are rebuilt**, from the tokens each row already carries and never by re-running the signals, whose windows are measured from now. Rows whose score cannot be reproduced keep their number and their reasons; if one was actionable it is demoted and stamped rather than given an invented score. Database version 11.
* **New: repeat ad visits.** Extra entries by ad from the same browser within its 24-hour session cookie — a figure your Ads account cannot produce, because it mints a fresh click id per click and cannot tell they came from one browser. Counted only on ids that are unique per click; the aggregated `gbraid`/`wbraid` repeat by design and are left out. Shown as an observation, with what it does not establish written next to it.
* **New: a read-only Google Ads script** for reconciliation only. The existing script can add and remove IP exclusions, which is correct for the review queue and wrong for anyone who wants nothing but the comparison. The new one contains no exclusion code at all.

= 4.1.0 =
* **Fixed: aggregated click ids were written off as re-opened links.** Google mints a fresh `gclid` per billed click, so a second row carrying one is a re-opened link rather than a second charge. `gbraid` and `wbraid` do not work that way — several genuinely billed clicks legitimately share one. On the account this was found on, 45 rows produced by 26 distinct ids had been recorded as never billed when they were billed. Those rows are restored.
* **Fixed: a datacenter could take a click's billing slot from the visitor who earned it.** Where several rows share one click id, the row counted as the billed click was chosen on user agent alone, so a link previewer arriving first took the slot. The election now excludes datacenter origins.
* **Fixed: retention could delete the row holding the slot**, leaving the group with none and the repair pass only looking back 48 hours. Repair now runs before deletion and is not limited by age.
* **Fixed: verdicts from rules this plugin has withdrawn were still nominating addresses for exclusion.** Every row is stamped with the ruleset that decided it, and no query read the stamp. On the account this was found on, all eight suggested addresses came from withdrawn rulesets and none from the current engine — one was a Google datacenter checking the ad. Only the current ruleset may nominate an address now. Inherited verdicts stay visible, counted separately and named as inherited.
* **Fixed: one address could exhaust the site's daily measurement budget**, after which nothing else was recorded until midnight — indistinguishable from a quiet day. New sessions from one address now have a budget of their own; visits already being measured keep reporting.
* **Fixed: the exclusion list a person downloads ignored the allowlist**, while the automated feed honoured it. An address approved one week and allowlisted the next stayed in the file and was pasted into the account by hand.
* Database version 10.

Older releases are listed in CHANGELOG.md, which ships with the plugin. They are kept out of this file because a readme this size risks tripping the directory's parser, and because the history of a scoring engine is worth reading in full rather than in a summary.

== Upgrade Notice ==

= 4.2.0 =
Findings will drop. The signal that scored a visitor for returning through your ad several days running is removed — it was flagging repeat customers — and stored verdicts that rested on it are rebuilt. Nothing is deleted.

= 4.1.0 =
Clicks with an aggregated id (gbraid/wbraid) were recorded as never billed and are restored. Findings from rulesets this plugin has withdrawn no longer suggest addresses to exclude, so the review queue may empty. Nothing is deleted.

= 4.0.0 =
Your findings will drop, sometimes sharply. Two signals could agree while measuring the same network, and one learned from the plugin's own past verdicts. It is removed and stored findings are re-read without it. Nothing is deleted.

= 3.0.0 =
Visitor-facing cloaking is retired and cannot be re-enabled. Automatic IP exclusions are off until you approve addresses one by one. Findings resting on a single signal are labelled "suspicious" rather than actionable, so counts may drop. No data is deleted.
