=== ClickHelm ===
Contributors: clickhelm
Tags: click fraud, google ads, ppc, ad fraud, bot detection
Requires at least: 5.6
Tested up to: 7.0
Requires PHP: 7.2
Stable tag: 6.88.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Spot the paid clicks that are wasting your budget. Identifies visitors by device, so a block follows the person, not the address.

== Description ==

**ClickHelm is free to use, with no time limit and no card.** One site, up to 500 visits a
month, and it shows you everything it sees: every visitor it recognises, the score it gave
them and why.

What a licence adds is doing something about it. Blocking, your own rules, reports, the weekly
email, and connecting your Google Ads account - which of the clicks you paid for never turned
into a real visit, what they cost you, a refund claim to Google, and an exclusion list that keeps
itself up to date - are the paid part. The free edition sees everything and stops nothing.


ClickHelm watches who arrives on your site from Google Ads, works out which of them
are costing you money without ever becoming a customer, and lets you stop them.

**It blocks the person, not the address.** Identity comes from a device fingerprint
resolved on the server, so a visitor you block stays blocked after clearing their storage,
switching browser, or moving from home WiFi to mobile data. Blocking by IP address alone,
which is all an outside service can do, is undone by turning a phone's data off and on.

**Nothing is blocked without you.** The plugin ranks visitors, explains its reasoning in
plain language, and waits. The only exception is the click-velocity rule, and it stays off
unless you deliberately switch it on. This is a design decision, not a missing feature: a
tool that blocks your real customers automatically costs more than the fraud did.

= What it shows you =

* **Dashboard** — who is worth blocking today, ranked, with the reason and a button
* **Visitors** — everyone seen, searchable and filterable, with the evidence behind each score
* **Google Ads** — spend, waste and profit per campaign, ad group, keyword and placement
* **Reports** — country, network operator, address range, device and behaviour breakdowns
* **Rules** — your own conditions, which can raise risk, email you, exempt someone, or block
* **Possible Duplicates** — fingerprints that probably belong to someone you already know

= What it measures =

Revenue is read from the actual WooCommerce order on the server, so it counts even when a
shopper blocks scripts, and it is the real total rather than an estimate. That is what makes
genuine per-campaign profit and loss possible.

Calls, WhatsApp taps, form submissions, thank-you pages and your own buttons all count as
leads, so the plugin works for a service business as well as a shop.

= Email =

A weekly or monthly report summarising what was caught, what it saved you, and who is worth
blocking, with a link straight to each decision. Rules can also send an instant alert, and
alerts are batched into one email per window so a busy afternoon cannot fill your inbox.

= Privacy =

Visitor data stays in your own database. The one thing that leaves it is visitor IP
addresses, for address classification: they go to api.clickhelm.com, which asks proxycheck.io
and keeps none of them. It is on, because it is what the plugin is for - see External services
below, and say so in your site's privacy policy. Old data is cleaned up automatically on a
schedule you set.

== External services ==

Every request below leaves from your own server. Nothing is ever sent from a visitor's browser.
This plugin does not check a licence, does not look for its own updates - updates come from
WordPress.org like any other plugin here - and sends no usage reports. The one thing our server
learns about your site is described under Address classification below: that it asked, and when.

**Google Ads** (googleads.googleapis.com), only with a licence, and only if you connect an account

If you choose to connect Google Ads, the plugin reads your own campaign reporting once a day -
click identifiers, campaign and keyword names, and cost figures - so it can compare the clicks
recorded on your site against the clicks Google actually charged you for.

It changes two things in the account, and only when you switch them on in the plugin: it can add
ClickHelm's tracking template to the account, and it can keep an account-level IP exclusion list
made from the visitors you blocked (never anybody you did not block, and never exclusions you added
yourself). It never touches campaigns, ads, budgets or bids. Our server builds those two changes
itself and refuses any other kind.

The request is routed through api.clickhelm.com because Google requires credentials that cannot
be shipped inside a plugin; the reporting data is passed straight through to your site and is
not stored on our server. You can disconnect at any time.

What is read and why: https://clickhelm.com/google-ads-data
Terms: https://clickhelm.com/terms
Privacy: https://clickhelm.com/privacy

**Address classification** (api.clickhelm.com, then proxycheck.io)

This one is on, and it is what the plugin is for. A visitor arriving from a data centre, a VPN
or a commercial proxy is the cheapest kind of fraudulent click there is, and telling them apart
from a real customer cannot be done on your own server - it needs a database of who owns which
network, kept current by somebody whose job that is.

So the plugin sends visitor IP addresses to api.clickhelm.com, which passes them to
proxycheck.io under our account and hands the answer back: country, network operator, and
whether the address belongs to a VPN, proxy, Tor exit or data centre. Each address is looked up
once and remembered on your site, so a returning visitor costs nothing.

Our server keeps none of the addresses. They are relayed and discarded within the request; what
it records is how many were classified, never which - together with the address of the site that
asked, the plugin version and the time. That record is what enforces each site's daily allowance,
and we also use it to count how many sites run the free edition. You do not need an account
anywhere and there is no key to enter.

The same answer can carry short notices from ClickHelm - that a new version is out, or something
about security - which the plugin shows at the top of its own screens, never elsewhere in
WordPress, in whichever of English or Arabic you read ClickHelm in. Nothing is sent to ask for them,
and each can be dismissed.

Because visitor IP addresses leave your server, say so in your site's privacy policy.

Terms: https://clickhelm.com/terms
Privacy: https://clickhelm.com/privacy
proxycheck.io terms: https://proxycheck.io/terms
proxycheck.io privacy: https://proxycheck.io/privacy

== Installation ==

1. Upload the plugin folder to `/wp-content/plugins/`, or install the zip from
   Plugins → Add New → Upload Plugin.
2. Activate it. The database tables are created automatically.
3. Open **ClickHelm → Settings** and set your average cost per click, so the plugin
   can show what traffic is costing you rather than hiding every money figure.
4. Open **ClickHelm → Google Ads → Setup & names** and paste the tracking template
   into Google Ads. Without it, Google does not tell the plugin which campaign a click came
   from, and that information cannot be recovered afterwards.

== Frequently Asked Questions ==

= Can it get my money back from Google? =

It can help you ask, and Google decides. Google credits the invalid clicks it detects by
itself, automatically. For the ones it missed you can ask it to investigate any click from the
last 60 days, through its Click Quality form, and it wants evidence only your website has:
each click's IP address, browser and click id, and why it looks invalid. **Google Ads →
Refund claim** puts that together - an evidence file, and a letter in English to paste into
the form. Nothing guarantees a refund, and be wary of anything that promises one. What the
plugin does by itself is stop the same person costing you again, and show you which
campaigns and keywords are worth cutting.

= Why does it not block anything on its own? =

Because a wrong block is more expensive than the click it prevented. The plugin ranks and
explains; you decide. If you want automation, the click-velocity rule and per-rule
auto-blocking are both there — they are just off until you turn them on.

= Will blocking someone hurt my SEO? =

No. Search engine crawlers are never blocked, whatever their score, and the block page
returns HTTP 200 with a noindex header rather than an error.

= I blocked someone and they came back. =

They did not get in — check the visitor's page. If the same person appears as a new visitor,
open **Possible Duplicates**: the plugin has probably already spotted the match and is
waiting for you to confirm it. Lower the confidence threshold in Settings to catch more.

= Does it work with page caching? =

Yes. The block page is never cached, and blocking, unblocking and updating all flush the
cache. Ordinary pages stay cacheable; a blocked visitor served a cached page is still
stopped in the browser.

= What happens to my data if I delete the plugin? =

Nothing, unless you asked for it. Deleting leaves your visitors, blocks and history intact
so a reinstall picks up where you left off. To erase everything, tick the option under
Settings → Housekeeping first.

== Changelog ==

= 6.88.0 =
* **Fixed: your visitors’ network operator and connection type were never being stored.** Our
  classification service and the plugin disagreed about what four of the fields were called, so
  since late August they arrived empty on every install. That quietly emptied Reports → By network
  operator, the genuine-or-impostor check on crawlers, and any rule matching a network operator.
  Addresses already classified without an operator are looked up again by themselves, a few at a
  time. **Connection types are now the classifier’s own words** — VPN, Tor, Hosting, Residential,
  Scraper — so a rule on "connection type" can match what actually arrives.
* **A new install no longer opens in Egyptian pounds.** The currency is taken from WooCommerce
  where it is active, otherwise from your site’s own time zone, and the setup step now has the
  full list beside the cost-per-click box instead of a fixed label.
* **Fixed: "The link you followed has expired" during setup.** On the free edition, saying you run
  ads, declining the licence and then entering a cost per click ended on WordPress’s error page.
  Your figure was saved; the page died anyway.
* **"Delete their data" now deletes the address too.** What had been learned about a visitor’s IP
  address stayed behind, with its city, after the visitor was erased — so the confirmation was not
  quite true. An address another visitor still uses is left alone.
* Wording on the free edition that contradicted the screen beside it: the Google Ads tab no longer
  offers "Setup" as a way to connect an account the free edition cannot connect, spend estimated
  from your own rate is no longer called a real cost, and nothing says Google is about to confirm
  clicks on an edition that never talks to Google.
* Exclusion lists counted every page view from a flagged visitor, so ordinary organic visits
  appeared as "clicks with no campaign recorded". They now count paid clicks only.
* Turning on automatic blocking by click speed can no longer be saved without a licence, rather
  than being stored and quietly ignored.

= 6.87.0 =
* **The plugin now speaks French.** Every screen, notice, report and email, chosen per person
  under Settings → Language, so one administrator can read it in French while WordPress itself
  stays in whatever language the site runs in.
* The release check now compares catalogues the way gettext does, by context as well as by the
  English — a catalogue could previously be reported as complete while every short label that
  depends on its context was still in English.

= 6.86.0 =
* **Rule alerts can go to Slack, Discord or any webhook**, as well as to email and never instead of
  it. Paste an incoming webhook under Settings → Email reports and alerts arrive in the channel; the
  same body also carries the rules, the visitor counts and a link, for anything wired up by hand.
* A **Send a test** button beside it, because a webhook nobody has tested is a feature that looks
  configured and has never carried anything.

= 6.85.0 =
* **Answering a privacy request.** Settings → Data requests looks a visitor up by the address they
  visited from, or by their visitor identifier, shows everything held about them, hands it over as a
  file, and deletes it.
* **WordPress's own Tools → Export and Erase Personal Data now include ClickHelm**, where an email can
  be tied to a visitor - which on a WooCommerce site an order does. Where it cannot, the answer says so
  and points at the lookup instead of quietly reporting nothing.
* **Suggested wording for your privacy policy**, offered in WordPress's privacy policy editor: what is
  recorded, where it is kept, what leaves the site, and for how long.
* Deleting the data of a visitor you have blocked keeps the identifier and the block and clears
  everything that described them, unless you choose to delete the block as well. Erasing it silently
  would undo the block, and the plugin will not do that behind your back.

= 6.84.1 =
* **The setup walks both ways.** Back and Next on every step, and Finish on the last one, so you can
  check what you typed two screens ago instead of starting again.
* **Without a licence, saying "yes, I run ads" now says what that would mean.** Connecting a Google Ads
  account is part of a licence, so the free edition explains that instead of walking you into a step
  about a connection it would refuse - with a way to see the pricing, and a way to put it aside. Put
  aside, that step is marked as such and stepped over in both directions.
* **The tracking template step stays either way.** It needs no connection: paste the template into
  Google Ads yourself and the campaign, keyword and placement behind every click start arriving, which
  is what every Google Ads screen in the free edition is built from.

= 6.83.3 =
* **Fixed: other plugins' notices appeared inside ClickHelm's screens** - and, in the setup, inside the
  card you were reading, at every step. WordPress moves every notice to just after the first heading on
  the page; ClickHelm's first heading was inside its own header, and the setup had none at all. Every
  screen now begins with its own heading, so those strips stack above ClickHelm rather than through it.
* ClickHelm's own "campaign data is incomplete" warning now sits directly above the plugin, under
  WordPress's notices, instead of at the very top of the page.

= 6.83.2 =
* **Fixed: a new install said "0 visits" for six hours.** The plan screen's visit count is cached, and a
  freshly activated plugin is opened before anybody has visited - so it cached a zero and held it, while
  Visitors filled up behind it. A zero is now rechecked after five minutes; a real figure is still cached.

= 6.83.1 =
* **Fixed: Google Ads could say more clicks carried campaign data than there were paid clicks** -
  "51 of 19", seen on a live site. It counted every page view carrying a campaign, second pages
  and return visits included; it now counts paid clicks, as the total does.
* The description no longer suggests the free edition can connect a Google Ads account. It cannot:
  connecting one is part of a licence, and so are the figures, the refund claim and the automatic
  exclusions that come from it.

= 6.83.0 =
* **ClickHelm can add its tracking template to your Google Ads account for you.** With the
  account connected it is one press - in the setup, on Google Ads → Setup, or on the warning
  itself - instead of copying a template into Google Ads by hand. An account that already has a
  template from another tool is left alone, and you are shown how to combine the two. Campaigns
  with their own template, which Google uses instead of the account's, are named.
* **A warning at the top of every ClickHelm screen while campaign data is incomplete** - until
  the tracking template is in place, clicks do not say which campaign sent them, and those days
  cannot be analysed later.
* **Automatic exclusion in Google Ads.** Switch it on under Google Ads → Exclusion lists and the
  addresses of the visitors you block are kept in your account's own IP exclusion list, at account
  level, so it covers every campaign, Performance Max included. Only visitors you blocked; an
  address a real customer also used is left out; exclusions you added yourself are never touched,
  and one you remove in Google Ads is never put back. Google allows 500; the costliest are kept.
* Google Ads → Setup no longer asks you to name campaigns and ad groups by hand: the names arrive
  from Google once the account is connected.
* **Dashboard:** each part of "Where the waste is coming from" sits in its own frame, devices are
  named in full (Mobile, not "m"), and a country no longer appears twice under its name and its code.
* **Help:** a button opens the contact form on clickhelm.com.
* **Heatmaps are hidden while they are rebuilt.** Nothing is recorded for them meanwhile, and
  what was recorded is kept.
* The Exclusion lists screen no longer says there is no way to tell Google about invalid clicks.

= 6.82.0 =
* **Google Ads → Refund claim.** Google will investigate clicks from the last 60 days if you
  ask, and it asks for what only your website has. This screen gathers the clicks Google
  charged you for that came from visitors you blocked or that scored high risk, with each
  click's id, time, IP address, browser, landing page and the reason it looks invalid, as an
  evidence file - and writes the letter to paste into Google's Click Quality form. Google
  decides; nothing here promises a refund. Available in the free edition too.
* **A visitor can no longer choose the address they are recorded under.** The headers proxies
  use to pass an address on were believed on every site, and anybody can write them. They are
  now believed only from Cloudflare, from a proxy on your host's own network, or from a proxy
  you name. On a site behind neither, a bot sending invented addresses is now recorded under
  its real one - and can no longer put somebody else's address into your Google Ads exclusion
  list.
* **Settings → Visitor addresses.** Shows how addresses are read, lists anything seen
  forwarding visitors that ClickHelm does not recognise, and lets you trust it. The health
  panel says so if most of your visitors are being recorded under one address.
* The readme's privacy section said address classification was off by default. It has been on
  since it moved to our own account, as the External services section says. Corrected.

= 6.81.0 =
* **Notices from ClickHelm now appear at the top of ClickHelm's screens** - that a new version is
  out, something about security, or something worth knowing. In Arabic or English, whichever you
  read ClickHelm in, and only on ClickHelm's own screens, never across WordPress.
* **Nothing new is sent to fetch them.** They arrive on requests the plugin already makes: the
  address-classification answer, and for a licensed site the licence check.
* Every notice can be put away with the cross beside it, and stays away for you. One marked critical
  stays until it ends.

= 6.80.1 =
* **The readme now says exactly what our server learns from an install.** Address classification
  has always told api.clickhelm.com which site was asking, with the plugin version. The text said
  the plugin sends no usage reports, which is true, but not that this record is also how we count
  sites running the free edition. It says so now. Nothing the plugin sends has changed.

= 6.80.0 =
* **Setup now opens by asking which language you want.** The first screen reads in Arabic and
  English at once, with a button for each, and every screen after it follows the choice. It used
  to live only in Settings, which is not where anybody setting a plugin up for the first time goes
  looking.
* **Choosing English now works on an Arabic WordPress.** English has no translation file, and the
  language setting stopped at the missing file - so somebody whose WordPress is in Arabic kept
  reading ClickHelm in Arabic whatever they picked.
* **Your account at clickhelm.com can now show how many visits ClickHelm watched over.** A third
  daily count travels with the licence check, beside ad clicks stopped and paid clicks flagged: the
  number of visits by people each day. A count, like the other two - nothing about who visited or
  what they looked at, and crawlers are not counted.

= 6.79.0 =
* **Housekeeping before submitting to the WordPress.org directory.** The licence is now stated in
  the plugin file itself as well as in the readme, a query string value that was only ever
  compared is sanitised anyway, and the one place that decodes base64 - unwrapping an encrypted
  Google token - says so beside itself. Nothing about how the plugin behaves has changed.

= 6.78.0 =
* **Usage no longer counts traffic from before you subscribed.** The figure on the Licence screen
  is measured over your billing period, which is right - but it was cached for six hours and
  nothing threw that away when a key was activated, so a plan bought an hour ago could open
  showing a month of earlier visits already spent against it.
* **And it now says which period it means**, with the dates it runs between. "Last 30 days" was
  the wrong name for a window that runs from one renewal to the next.
* **A licence that stops now stops within minutes.** A cancelled or refunded licence kept working
  on the site until its next scheduled check, up to twelve hours later. Nothing new is asked for:
  the address-classification call already happens every few minutes, and it now carries word that
  the site should go and check its licence properly.
* **"Activate" is no longer offered on a licence that is already active.** The main button is
  Disconnect, and Activate comes back by itself as soon as you put a different key in the box -
  which is the only thing it was ever for.

= 6.77.0 =
* **Possible duplicates can be got through now.** Two live sites were carrying 76 of these with
  nobody deciding any of them, and the screen was part of the reason: every match wanted its own
  press. You can now confirm every match at or above a confidence you choose - the list says how
  many that is before you press, and how many of them have a blocked visitor on one side, because
  merging one of those blocks the other person too.
* **The confidence counts are now the filter.** "12 at 90% or more" was already the answer to
  which of these to look at first; it just was not clickable. It is now.
* **Every signal on the evidence table shows what it is worth.** A match is a weighted score, and
  the table listed which signals agreed without saying which of them mattered - so a 15-point
  agreement and a 3-point one read as two equal facts. Heaviest first, with the weight, and with
  the ones the score never counted marked as such.
* **And the matches the current rules would no longer raise.** A match is scored once and never
  looked at again, so when a rule tightens it never reaches the ones already waiting - fifteen of
  those 76 were pairs of different phone models, which stopped being a match on 4 September. They
  are marked on the screen and can be cleared in one press.
* Fixed: a possible duplicate could lose one of its two sides to the routine cleanup and go on
  asking to be decided - "No longer on file" on one half, two buttons underneath, and a number in
  the header counting a decision nobody could make. Those are now cleared with the record.
* Fixed, in Arabic: "the oldest has been waiting 1 day" read as "two days". The catalogue carried
  four plural forms where Arabic needs six, so a count outside them borrowed the wrong wording -
  a fluent sentence with the wrong number in it. Two email warnings had the same fault.

= 6.76.0 =
* **A locked feature now says so when you press it, not after the page reloads.** Blocking a
  visitor without an active licence was refused by the server and always has been - but what you
  saw was a page reload and a small note above a long table, while the row you clicked still
  offered Block. A dialog explains it at the moment of the press instead, and a switch you cannot
  use is put back where it was.
* **And the settings that quietly did nothing.** The weekly report, alerts, heatmaps and
  automatic blocking could all be switched on without a licence. They saved, they said "Saved",
  and none of them ever ran - a report that never arrives is something you might not notice for a
  month. Those are marked too.
* Fixed: the Possible duplicates screen was the one place offering a Block button and saying
  nothing at all when it was refused.
* **Two fingerprints that report different phone models are no longer treated as one person.**
  Measured on two live sites before it was written: fifteen linked pairs carried a device model
  on both sides and every one of them disagreed - a Samsung against a Huawei, a TECNO against an
  Infinix - while the match was rated 70% to 82%. Two of them had already been rejected by hand.
* **You decide when two fingerprints merge without being shown to you.** Never, or from 75% to
  100%, in Settings under Blocking. It still defaults to 95, so nothing changes unless you change
  it - and only the percentage moves: a merge still needs enough comparable evidence to mean
  anything, and still needs one of the two hardest-to-fake signals to agree.
* **Possible duplicates rebuilt around the decision it is asking for.** It now says what
  confirming would actually join - the visits, the ad clicks, the leads and their value - and
  warns you when one of the two is blocked, because confirming makes the other one blocked as
  well. Each side is shown as a person: when it was first and last seen, how much traffic it
  brought, how many addresses it used, with a link to each. The strongest matches come first
  rather than the newest, there is a count of what is waiting and how long the oldest has waited,
  and the list finally admits when there are more than the two hundred it shows.

= 6.75.0 =
* **Fixed: the Licence screen contacted our server every time you opened it.** The answer is
  meant to be kept for twelve hours, but a rule that refreshed a "stale" one was written so that
  it also matched the perfectly current one - so a site running the newest version, which is most
  of them, refreshed on every single view. The screen waited on the network each time, and would
  have waited out the full timeout on a morning when that server was slow. It now uses the cached
  answer, and works out whether an update exists from the version actually running rather than
  trusting a flag written before the last update changed it. That screen went from up to three
  seconds to nothing.
* **Fixed: an email address the plugin cannot use was accepted in silence.** Type an address with
  a missing `.com` into the report or alert box and it saved, the screen showed it saved, and the
  report quietly went to the site's admin address instead - for as long as nobody thought to
  check. Nothing was ever lost, but the wrong person was reading it. Both boxes now name any
  address that cannot receive, and say exactly where the mail goes instead.
* **Fixed: the support details on the Help screen were half translated.** The row names were in
  your language and the answers beside them were not, so an Arabic install read "آخر فحص
  للترخيص: never" and "الترخيص: active / unlicensed". The table now reads properly in Arabic,
  including the licence state and how many plugins are active. The block you copy into an email
  deliberately stays in English, because somebody at this end has to read it.
* Fixed a PHP warning raised by the Reports screen whenever there was revenue to show and no
  comparison period - harmless on screen, but it filled the site's error log.
* Everything above was found by exercising the plugin rather than reading it: every screen in
  every state it can be opened in, every button that changes data including the ones that delete
  it, all 53 settings saved with values chosen to break them, and the public tracking endpoint
  attacked with oversized, malformed and hostile payloads. **Twenty-four of twenty-six hostile
  settings values were already rejected or clamped correctly**, nothing got past the tracking
  endpoint, and the scheduled jobs ran clean.

= 6.74.0 =
* **Fixed: a click id your account never reported could still be counted and priced.** One
  arrival in the same ten days carried a real, correctly formed click id that did not appear
  anywhere in the click report downloaded from the Google Ads account - on a day Google had
  reported other clicks for. It was counted anyway, because nothing ever compared the two.
* Now it is compared, but only where the answer means something: the day has to fall inside the
  span of days the click log actually covers. Before the first day imported, or after the last
  day Google has reported, an unlisted click id is left exactly as it was and nothing is said
  about it - a gap in what has been reported is not evidence that a click did not happen, and
  your figures are never reduced on a guess. A site with no account connected is untouched.
* The address of an arrival is now only read when no click id was stored with it, which is the
  older history this fallback was written for. It used to be read as an alternative, so it
  answered for arrivals the click id had already settled - and since a real click id appears in
  the landing address as well as in its own column, the check above would have done nothing at
  all. It was found that way in the lab, before release, and the test now covers it.
* All four places that decide "this was a paid click" are built from one expression. Six copies
  of that rule drifting apart is what caused the fault fixed in 6.73.0.

= 6.73.0 =
* **Fixed: visits that were never paid clicks were counted and priced as paid clicks.** Google's
  tracking template writes `gclid=` into every landing address it builds. When somebody comes
  back through a bookmark, their browser history or a link they were sent, that address arrives
  with the whole template intact and the click id empty - and the money queries matched on the
  parameter's *name*, so every one of those returns was counted as a fresh click and charged at
  your account's own rate.
* On the account this was found on, **fifteen of thirty-two arrivals** counted as paid clicks
  over ten days were exactly that, on days Google had reported no clicks at all. The visitor
  records were right the whole time - they said "0 ad visits" for the same people - because the
  check made when a visit is recorded has always demanded a real click id. Only the six
  hand-written copies of that rule in the reporting queries had drifted from it.
* Those six copies are now one, so they cannot drift again, and it demands what the original
  always did: a value after the `=`, and the parameter anchored to a `?` or `&` so an address
  carrying something like `?notgclid=` no longer qualifies either.
* If your figures drop after this update, they were too high before. Nothing was removed except
  clicks nobody was charged for.

= 6.72.0 =
* **Fixed: two whole sections of the Reports page were always empty.** "By address range" and
  "Engagement quality by country" each asked the database for a date range and were handed only
  the start of it, so the query was refused and returned nothing. The page then printed its own
  "no data yet" message, which read as an honest answer rather than as a fault. Both work now.
* **Fixed: the "landed and left without scrolling" signal always read zero**, for the same
  reason, in the chart explaining why traffic gets flagged.
* **Fixed: the heatmap device filter.** With no device chosen the page ended up filtering on an
  empty value instead of "all", so no filter button was highlighted and every link it built
  carried an empty setting.
* **Four notes on the dashboard and the whole fabricated-clicks warning on the Google Ads page
  were in English on an Arabic screen.** All translated, including the counts, which now use
  real plural forms rather than an "s" added to the end of a word.
* The locked screen said "Rules" in English while every other one was translated.

= 6.71.0 =
* **"Phone, WhatsApp & forms" is no longer a label that cannot be changed.** It was a badge
  reading "tracked automatically" with no setting behind it, so every form on the site counted
  as an enquiry - the search box, the newsletter field and the login form included, which is
  rarely what anyone meant. Phone taps, WhatsApp taps and form submissions now switch on and off
  separately, and you can name which forms count by id or class.
* **What a lead is worth.** Only shop orders and the developer hook ever carried money, so a
  clinic or a law office saw leads and an empty revenue column no matter how well it was doing.
  Give a phone tap, a WhatsApp tap or a form an average value and every money figure starts
  working. It is an estimate and is labelled as one; a real order always uses its real total.
* **Each rule now says how often it actually matched.** "Never matched" is the useful half: a
  thank-you address or a button selector that has done nothing for a month is either wrong or
  waiting, and until now there was no way to tell which without doubting the whole total. The
  plugin has always recorded which rule produced each lead and never showed it.
* **Leads from people signed in to your site can be excluded**, so testing your own contact form
  does not appear in your own report. Their visit is still recorded; only the lead is not.
* **A cool-down for repeats.** The same visitor tapping the same phone link three times was
  three enquiries. Set a number of minutes and it is one. Zero keeps the old counting.
* Every default preserves exactly what the plugin did before, so nothing changes on an existing
  site until you choose to change it.

= 6.70.0 =
* **Fixed: a thank-you page counted a new lead every time it was refreshed.** Reaching the page
  was the whole event, with nothing remembering it had already happened, so a refresh, the back
  button or a reopened tab each counted again. One booking became four in testing. It is
  remembered for the session now, keyed on the address, so a reload is the same lead while a
  second order at a different address still counts properly.
* **Fixed: a WooCommerce sale counted twice.** The order was recorded on the server with its real
  total, and then the order-received page matched the thank-you list and recorded it a second
  time with no value. The count doubled while the revenue did not, so cost per lead read twice as
  good as it was. The settings box suggests "/order-received" in its own placeholder, so this was
  waiting for the first shop that followed it. WooCommerce's own address is now removed from that
  list whenever order tracking is on.
* **A thank-you address of just "/" is ignored.** It matches every page there is, so every page a
  visitor opened became a lead. It cannot express "the home page" either, which is what anyone
  typing it meant.
* **Thank-you addresses are matched without case.** "/Thank-You" typed the way the page title
  reads never matched the lower-case address WordPress serves, so the setting was accepted and
  quietly did nothing.

= 6.69.0 =
* **Fixed: campaign numbers where the names should be.** The new dashboard section and the Google
  Ads exports printed the bare campaign id instead of the name you gave it. They were looking the
  id up in the wrong place — the name list is keyed by type, not by id, so the lookup missed every
  single time and fell back to the number. Both now use the same resolver every other screen uses.
* **The health section at the foot of the dashboard is a full panel.** Every check shows what it
  actually measured: how many paid clicks carried campaign data and when the last one did, when
  WordPress last ran the scheduled work, how many visits were recorded this week, what state the
  licence is in. Anything wrong sorts to the top and carries a link to where to fix it. A passing
  check that only says "fine" is asking to be believed; one that shows its figure can be read.

= 6.68.0 =
* **"What the waste is costing you" now only reports patterns.** It was ranking purely by money,
  so on a quiet account a search term with a single click could top the list reading "1 of 1
  wasted, 100%". One click is an incident. A row now needs at least eight clicks in the period
  before it can appear at all, and then either repeated clicks from people you blocked or scored
  high risk, or steady spending with no call, message, form or order to show for it. Each row
  says which of the two it is, in a sentence, instead of three figures to interpret.
* **Both new dashboard sections now say when there is nothing to report.** Rendering nothing at
  all makes a working section indistinguishable from a broken one, which is how "where is it?"
  becomes the first question rather than the last.

= 6.67.0 =
* **The dashboard says what changed, without being asked.** It now always measures the period
  you are looking at against the one before it, and puts the result in a sentence above the
  figures. The comparison selector still chooses what to measure against — it just no longer
  decides whether the measurement happens at all.
* **A new section says what the waste is costing you**: the search terms, placements or
  campaigns with the most money behind clicks you would not have paid for, and a link straight
  to the full table. The dashboard could already tell you how much was wasted; this is the first
  screen that says where to go and stop it.
* **"Worth fixing", at the foot of the dashboard.** Three things break this plugin without
  producing an error — a missing tracking template, WordPress not running its scheduled work, a
  licence never checked. When one of them is true it says so on the screen you actually open.
  When nothing is wrong it shows nothing at all.
* **Fixed: "background work last ran" was measuring your own visit.** It reported the later of
  WordPress’s scheduler and the run that happens when you open a ClickHelm screen — so on the
  Help page it always read "a moment ago", and the matching dashboard check could never fire.
  Both now ask about the scheduler on its own, which is the thing that was in question.

= 6.66.0 =
* **Exports you can actually open.** The file had no byte-order mark, so Excel read it as the
  machine’s own codepage and every Arabic word arrived as mojibake — which is what "the export is
  unreadable" meant. Column names are words now rather than database fields, HTML entities no
  longer print as "&mdash;" inside a cell, and the raw fingerprint column is gone.
* **The Google Ads tables can be exported too.** Campaigns, ad groups, keywords, placements and
  networks each have their own button. These are the screens that say where the money went, and
  until now they were the ones you could not take away with you.
* **Tell ClickHelm which clock and currency your advertising account uses.** Google reports each
  day in the account’s time zone; your website may be set to another one, and where they differ
  the small hours land on different days and the daily figures never quite match. The setup now
  asks, and it is on Settings beside the currency. A connected account still wins, because at
  that point the answer can be read instead of typed.
* **Column headings sit over their own numbers.** Numeric columns were right-aligned while their
  headings stayed left, on nearly every table in the plugin. And on Arabic installs every text
  heading sat on the wrong side of its column entirely.
* **Help has a place in the menu**, after Settings, in the WordPress sidebar and in the plugin’s
  own tabs — not only behind the button in the header.
* **"Recalculate scores" appears only when there is something to recalculate**, and says how many
  visitors are waiting. Every update already schedules this in the background; the button now
  exists for the one site where that background work is not running.

= 6.65.0 =
* **Help is a real page now**, reached from the button in the header of every ClickHelm screen.
  It carries the support address, the guides, a way back to the setup, and the thing the website
  cannot know: what this install looks like from the inside.
* **Two of those facts answer the question people write in about most often** — when your licence
  was last checked, and when WordPress last ran its background work. If that second one has
  never happened, the page now says so and explains what it means, rather than leaving you to
  wonder why a working plugin is showing you nothing.
* All of it can still be copied in one press for an email, and none of it is about any visitor.
* The strip that used to slide out under the header is gone. It did less and it was easy to miss.

= 6.64.2 =
* Help, in the header of any ClickHelm screen, now offers "Run the setup again". The setup is
  kept out of the menu on purpose — a permanent Setup item on a working plugin reads as
  unfinished business — but that left it reachable only by an address nobody had, while the
  release notes said otherwise.

= 6.64.1 =
* The Copy button on the setup screen sat on top of the tracking template and covered the start
  of it on Arabic installs, where the page runs right to left but the template inside it does
  not. It sits under the field now, in both directions.
* That button also failed silently when a browser refuses the clipboard - on plain http, or with
  the permission switched off. It selected the text and said nothing, which reads as a broken
  button on the one screen where giving up costs you a month of campaign data. It now says
  either "Copied" or "Selected — press Ctrl+C".
* Small things on the same screen: the list on the last step had lost its bullets, and the
  "skip setup" link was still offered on the step where there is nothing left to skip.

= 6.64.0 =
* **A short setup runs the first time you open ClickHelm.** It asks whether you run Google Ads,
  and if you do it hands you the tracking template with a Copy button and says where it goes.
  That one step is the only part of setting up ClickHelm that cannot be done later: until the
  template is in place Google does not say which campaign a click came from, and those clicks
  are recorded as visits but never as campaign spend. It is offered once, it can be skipped from
  any step, and Help in the header of any ClickHelm screen will run it again.
* Twenty-three lines on the free edition's plan screen were still in English on Arabic installs.
  They are translated, and the build now refuses to package a catalogue with any string missing
  from it - the reason nobody spotted these is that a missing translation quietly falls back to
  English and nothing anywhere calls it a fault.

= 6.63.0 =
* **Every ClickHelm screen now has a Help button in its header.** It opens the guides and a way
  to write to us - and, folded away beside them, the setup details worth pasting into that
  email: versions, whether WordPress's scheduler is actually running, and what the licence is
  doing. Nothing in it is about any visitor. It is there so the first reply you get can be an
  answer instead of a request for your PHP version.

= 6.61.0 =
* Two controls on the Licence screen were both called "Check again" - one asking whether a newer
  version exists, one asking the licence server whether your key is still good. They now say
  which: "Look for a new version" and "Check the licence now".

= 6.60.0 =
* **The network check now works out of the box, and it runs on our account.** Telling a data
  centre or a VPN apart from a real customer is the cheapest fraud signal there is, and it was
  switched off on nearly every install - because switching it on meant opening an account at
  proxycheck.io and pasting a key into a settings screen. Nobody does that. ClickHelm now holds
  the account: the plugin asks api.clickhelm.com, which asks proxycheck.io and hands the answer
  back. No account, no key, nothing to configure.
* **What that means for your visitors' addresses.** They now leave your server to be classified,
  where before they only did so if you had switched the lookup on. Our server keeps none of
  them - they are relayed and discarded inside the request, no database column holds one and no
  log line prints one, and what we record is how many were classified rather than which. If your
  site has a privacy policy, this belongs in it. The full description is in "External services"
  above and on https://clickhelm.com/security.
* The IP intelligence section in Settings has gone, along with the API key field and the choice
  of source. There is nothing left in it to decide.
* The "scheduled tasks look inactive" warning moved to Housekeeping, where it belongs: it is
  about cron, which everything in the background depends on, not about address lookups.

= 6.59.0 =
* **ClickHelm now has a free edition, and it starts the second you activate it.** No trial, and
  nothing counting down. Without a licence it records everything - every visit, every device it
  recognises, every score and the reasoning behind it - and, on up to 500 visits a month,
  connects to Google Ads to show which of the clicks you paid for never arrived and what they
  cost. A licence adds doing something about it: blocking, rules, reports, heatmaps and the
  weekly email.
* **The free edition receives updates.** It used to be told to buy a licence to install one. A
  plugin that can see a security fix and not apply it is not something worth shipping.
* The licence screen says *Free* rather than *Not active*, and no longer shows it in red.

= 6.58.0 =
* The licence page was reporting the Google Ads tab as paused on installs where it was working.
  Both columns of that table now read from what is actually true rather than from one shared
  answer.

= 6.57.0 =
* **Your account at clickhelm.com now shows what ClickHelm stopped, across every site you run.**
  Two daily counts travel with the licence check: ad clicks stopped, and paid clicks flagged as
  waste. Counts of what happened on your own site, never anything about a particular visitor,
  and no money figure - what a click was worth is priced from your own Google Ads account, and
  that stays on your server.

= 6.56.0 =
* **Google's permission screen now comes up in your language.** It was arriving in whatever
  language Google guessed from the country the request came from, so an English WordPress and an
  English ad account could still be sent to an Arabic screen. ClickHelm now tells Google which
  language the person pressing Connect reads.

= 6.55.0 =
* **Google's permission screen is explained before you meet it.** Connecting an ad account sends
  you to a Google screen asking you to allow "See, edit, create and delete your Google Ads
  accounts and data" - while ClickHelm has just told you it only reads. Both are true: the
  Google Ads API has a single permission covering the whole account and no read-only version of
  it, so every tool that reads your campaigns has to ask for that same one.

= 6.54.0 =
* **The device-recognition library is now served from your own site instead of a public CDN.**
  It was loaded from jsdelivr.net, which meant a company with no other part in this saw the IP
  address and the referring page of every visitor to your site, on every page view - and could
  have changed the JavaScript running on your pages at any time without any release of this
  plugin. It is the same library and the same version, so nobody you have blocked comes
  unblocked and no visitor is re-identified as somebody new.
* With this, a page on your site loads without contacting anybody at all. The only requests
  ClickHelm makes are the twice-daily licence check, and the optional address lookup you have
  to switch on yourself.
* Fixed: the tracking script did not declare that it needs the device-recognition library, so a
  caching or optimisation plugin that reorders scripts could load them the wrong way round. It
  failed silently to a much weaker method of recognising a device, which is the worst way for
  something like this to fail.

= 6.27.0 =
* **"Last 30 days" now means the same thirty days everywhere in ClickHelm, and the same thirty
  days Google means.** Rolling periods end yesterday, as they do in your Google Ads account.
  Today, Yesterday, a single day, a custom range and Last month all name their own boundaries
  and are unchanged.
* Nothing is lost from view: the dashboard's live list has never been bound to the chosen
  period and still shows the most recent arrivals whatever you pick, and Today is still there
  when you want today.

= 6.26.0 =
* **Click a keyword to see who clicked it.** Each keyword now opens its own clicks, one per
  row, with the visitor each one became and whether they did anything at all — the people who
  clicked and left are the ones worth finding.
* **Every click shows the keyword** that was searched, and its match type, in place of the ad
  group.

= 6.25.0 =
* **"Last 30 days" on the Google Ads tab now means the same thirty days Google means.** Its
  rolling periods end yesterday, as Google's do; ours ended today, so the two were a day
  apart and never agreed. Set to the same window they matched exactly. Today still has its
  own option when you want it.
* **The exact dates are printed above every table**, so the period is never something to work
  out.
* **Money figures no longer depend on having typed a cost per click.** A site that connected
  its Google Ads account and never opened Settings saw no money at all, on screens whose
  figures come straight from the account.
* Removed a sentence under the tables that contradicted the one before it — one said the spend
  was your account's, the other that it was a rate multiplied by clicks.

= 6.24.0 =
* **Campaigns, ad groups and keywords now come from your Google Ads report itself** — the same
  report the Google Ads interface draws. Clicks, cost and impressions are summed from it and
  nothing is derived, so the figures equal your account by construction rather than by
  correction.
* The previous version read Google's log of individual clicks, which is a different thing and
  does not agree with the account: one day it held five records against three charged clicks,
  and a month held fifty-eight against sixty-three.
* That log still does the one job it is right for — telling you which visitor each click
  became, on Every click and in the visitor column.

= 6.23.0 =
* **Phone calls and message taps are no longer counted as clicks that failed to arrive.** Over
  a month this read as fifty-two wasted clicks on an account whose clicks are mostly calls.
  Each row now says how many were meant to open a page and did not, and separately how many
  called or messaged you instead.
* **"Google charged" is gone from the tables.** The clicks column is Google's own count now,
  so the second figure only ever differed by click type — a distinction Every click already
  shows properly, one click at a time, with a name instead of a number.

= 6.22.1 =
* **Fixed: "Google charged" was being read over a longer period than the clicks beside it**,
  so it could show more charged clicks than clicks — 60 against 58. Both figures now cover
  the same days.
* Keyword, network and device rows say again that their spend is your campaign's real cost
  shared out across them. Google reports money per campaign, so only the campaign totals are
  lifted straight from your account.

= 6.22.0 =
* **Keywords, match types, networks and devices now come from your Google Ads account too**,
  the same as campaigns and ad groups. Google names the keyword on every click, so there is no
  longer any reason for parts of this tab to be counted one way and parts another — which is
  what every figure that had to be corrected here had in common.
* Placements remain counted from visits to your site, because Google does not put a placement
  on a click record. That is the one stated exception now, rather than a mixture nobody could
  keep track of.

= 6.21.0 =
* **Fixed: Repeat clickers was counting return visits as extra paid clicks**, so one person
  could appear to have cost more than a fortnight of real advertising. It is the screen where
  you decide whether to block a human being, so it now carries the same exclusions as every
  other money figure.
* Keyword and network spend now says plainly that it is your real campaign cost shared out
  across those visits, not a figure from your account — the campaign totals are the ones that
  match Google exactly.
* An empty Placements list now explains that Search campaigns have no placements, instead of
  reading as though something failed.

= 6.20.2 =
* **Fixed: "Arrived here" was reading zero on every row**, so the screen claimed not one of
  your clicks had reached the site.
* **Fixed: spend did not change with the period.** Seven days, thirty days and ninety days all
  reported the same figure. An earlier correction was still trimming every period back to the
  day this plugin started tracking — right when both columns were ours, wrong once the rows
  started coming from Google's own records.

= 6.20.1 =
* **Campaigns Google has never heard of no longer appear over longer periods.** Asking for
  thirty days when Google's click records reach back a week used to switch the whole screen
  over to counting visits, which brought back invented campaign ids. It now shows the days
  Google does cover, says which days those are, and keeps the figures matching your account.

= 6.20.0 =
* **Fixed: every keyword was claiming the whole campaign's clicks and spend.** Google reports
  cost per campaign, and that figure was being repeated onto every ad group, keyword and
  network row underneath it — so three keywords in one campaign each appeared to have had all
  three of its clicks. Those columns now appear only where they mean something.
* **Fixed: the first number now says what it is.** Where rows come from your Google Ads
  account it is Google's click count, so it is headed "Clicks", and arrivals get their own
  column beside it with how many never made it.
* **The screen says when it falls back to counting visits** and how far back Google's records
  currently reach, instead of silently changing what it counts and showing campaigns Google
  has never heard of.
* Google's click history now fills in about ten days per sync instead of one, so the full
  ninety days is there in a week or so rather than three months.
* Networks read "Google Search" and "Search partners" instead of "g" and "s".

= 6.19.1 =
* **The date you chose now survives everywhere on the Google Ads tab.** Picking a single day
  and then opening a campaign used to reset it, and correcting the date inside a campaign
  threw you back out to the campaign list. Switching tab lost it too. All of them now carry
  the day you actually chose.

= 6.19.0 =
* **Campaigns and ad groups are now your Google Ads clicks**, dated the day Google says each
  one happened — not our count of people arriving. That is why a day Google charged for
  nothing could still show clicks and spend: somebody arriving today on a click from
  yesterday was a click today, as far as the old screen was concerned.
* Keywords and placements still count arrivals, because Google does not send that detail with
  each click, and the screen now says so instead of leaving you to wonder.
* **Message buttons are named.** Google was sending a click type this plugin had never seen —
  a tap on a WhatsApp or message button. Charged like any other click, and the page was never
  meant to load.

= 6.18.1 =
* **Your past figures are corrected too.** Visits recorded before this version knew what a
  return was are checked in the background, a slice at a time, and the ones that were somebody
  coming back on a click id they had already used stop counting as paid clicks. The Setup
  screen says while it is running and reports what it found when it finishes.

= 6.18.0 =
* **Fixed: coming back was being charged to you as a new click.** A Google click id survives in
  a bookmark, a reopened tab or a shared link, so the same person arriving again days later was
  counted as a fresh paid click and fresh spend — on a day Google had charged for nothing. Your
  spend figures now match the ad account.
* **Return visits are shown, not hidden.** They appear on the click that brought the person in
  the first place: how many times they came back, and how long afterwards. Somebody returning a
  week later is the strongest evidence a click was worth its money.
* They still count as visits everywhere else. What they no longer do is count as a second click.

= 6.17.0 =
* **A phone call is no longer reported as a wasted click.** Google charges for a tap on your
  call extension exactly like any other click, and the page was never meant to load — so the
  previous version listed the best click you can buy as money lost. Every click now shows
  what was actually clicked: your headline, a sitelink, the phone number, directions.
* **"Never arrived" now means something.** Only a click that was supposed to land on your
  site can count as one that failed to. Calls, directions and taps on the ad image are shown
  separately and counted as nothing lost.

= 6.16.0 =
* **A single day is now its own option** in every date picker, instead of having to type the
  same date into both boxes of a custom range. The screen title says which day, so a
  screenshot still says what it is showing.
* **Currency is a list, not a text box.** A typo in it printed on every money figure on every
  screen. If your Google Ads account is connected, the currency it bills you in is shown
  beside the field.
* **Country and connection type in Rules are lists too.** A country typed by hand failed
  silently — "Saudi Arabia" never equals "SA", so the rule simply never fired and nothing
  said why.

= 6.15.0 =
* **New screen: Google Ads → Every click.** One row for every click Google charged you for,
  matched to the person who actually arrived — by the click id Google itself issued, so there
  is no guessing about which click is which.
* **It shows the clicks that never arrived.** You paid for them and nobody reached your site.
  Google cannot tell you this — it does not know what happened after the click. Your website
  cannot either — it never saw the click. Only the two joined together can.
* Each click shows the campaign, ad group, device and network in Google's own words, and
  beside them your visitor, their risk, and whether they called, messaged, sent a form or
  ordered.
* Where a click id was replayed for different people, the first genuine arrival is credited —
  a fabricated replay cannot steal the match.

= 6.14.0 =
* **ClickHelm now reads your Google Ads account's time zone and says so.** Google groups every
  figure by its own day, and a website on a different clock disagrees with it about which day
  the small hours belong to. The Setup screen now shows the account's clock, its currency, and
  how far your site sits from it.
* Groundwork for matching your ad spend click by click against the people who arrived: a new
  table that stores Google's own record of every click it charged you for.

= 6.13.0 =
* **New: Test click_view** on Google Ads → Setup. Runs one query against your account for a
  day you choose and reports exactly what Google returned — how many clicks, how many carried
  a click id, which networks and devices. Groundwork for matching your ad spend click by
  click against the people who actually arrived.

= 6.12.1 =
* **Fixed: the new "Google charged" column compared different periods.** Google reports a
  campaign's whole month; this site only knows the days since your tracking template went in.
  On a fresh install that read as "Google charged 62, 19 arrived here" when almost all of the
  difference was simply days nobody was watching. Both figures now start from the first day
  tagged clicks actually arrived, and the screen says which day that is.

= 6.12.0 =
* **Spend now matches your Google Ads account.** It used to be your arrival count multiplied
  by an average rate, which could not match the account for any period. Where Google has the
  figures for the dates on screen, that is what you now see — the number in the account.
* **New column: "Google charged".** Google bills a click on the ad; ClickHelm counts a person
  who reached your site. Those are different, always, and the difference is now visible
  instead of quietly averaged away — somebody who taps your ad and leaves before the page
  loads is charged and never arrives.
* "Ad clicks" is now called **"Arrived here"**, because that is what it has always been.

= 6.11.0 =
* **Campaigns Google has never heard of are now marked.** Anyone can put `&ch_campaign=12345`
  on a link to your site and invent a campaign that never existed. Once your Google Ads
  account is connected we know the real list, so anything outside it is flagged on the spot.
* Flagged, not deleted and not deducted. A campaign missing from Google might be invented, or
  it might be a real campaign on a different account than the one you connected — and those
  need different answers from you. Your figures do not move behind your back.

= 6.10.0 =
* **Choose the advertising account inside your manager account.** If your Google login sees
  one or more manager (MCC) accounts, ClickHelm now looks inside them and lists the actual
  advertising accounts. Managers appear as headings, not choices — Google will not report
  figures for a manager account, so offering one was offering a dead end.
* The account's real name is shown next to its number, so you are not picking from a list of
  ten-digit numbers.

= 6.9.1 =
* **Fixed: "Spend protected" was counting money you lost as money you saved.** Blocking
  someone turned every paid click they had ever cost you into savings, so the figure matched
  "Wasted spend" exactly while "Turned away" sat at zero. It now counts only paid clicks that
  arrived *after* you blocked them — which is the only kind that saved anything.
* The same correction applies to the emailed report and to the Visitors screen.
* "Still at risk" is now **"Already spent on high risk"**. That money has been charged
  already; what is at risk is that it keeps happening.

= 6.9.0 =
* **Campaign names arrive from Google.** No more typing a name for every id by hand, and
  again for every campaign you add. A name you type still wins — "Riyadh – AC cleaning" is a
  decision, and a sync must not quietly undo it.
* **Real spend replaces the estimate.** Cost per campaign now comes from Google itself
  wherever it has a figure, instead of one average cost-per-click applied to every campaign
  equally. Revenue was always measured from your actual orders, so this was the last
  invented half of every profit figure.
* Syncs once a day on its own. There is a **Sync now** button on Google Ads → Setup.

= 6.8.0 =
* **Connect your Google Ads account.** Google Ads &rarr; Setup now has a Connect button. It
  asks Google for **read-only** access and nothing else: ClickHelm cannot change a campaign,
  a budget or a bid, and it still never adds an exclusion on your behalf.
* The connection is authorised through Google's own consent screen and can be revoked at any
  time, from that screen or by pressing Disconnect here.
* The stored authorisation is encrypted with your site's own security salts, so a stolen
  database without your `wp-config.php` is of no use to anyone.

= 6.7.0 =
* Your plan allowance is now measured against your billing month rather than a rolling
  window, so it resets on a date you can see rather than drifting.
* Going past it pauses blocking new visitors and the reporting screens until it resets or you
  move up. **Everyone you have already blocked stays blocked**, and visitors keep being
  recorded — that never stops, for any reason.

= 6.6.0 =
* Your Licence screen now shows how many visits your site had in the last thirty days, and
  how much of your plan that is. It is the one figure you cannot work out for yourself.
* Going over your plan switches nothing off and charges nothing. You are told, and you move
  up when it suits you.

= 6.5.0 =
* Fabricated paid clicks are now detected and kept out of your money figures. Anyone can put
  a fake gclid on a URL and, until now, that counted as a click you paid for — which meant a
  competitor could make a profitable campaign look like it was burning budget.
* Three checks: the click id must be the right shape, the same click id cannot belong to two
  people, and one address cannot produce twenty different click ids in an hour.
* The Google Ads tab now says plainly when this is happening, and how. The clicks are kept
  rather than deleted, because the pattern is the evidence.

= 6.4.1 =
* Fixed visitor times being out by your site's timezone offset — someone who arrived
  seconds ago could read as "3 hours ago". Times were stored in your local time and
  compared against UTC.
* Fixed an empty tracking parameter counting as a paid click. Testing a tracking template
  produces a URL with an empty gclid, and that was enough to report a paid click on a site
  with every campaign paused.

= 6.4.0 =
* Security: the public tracking endpoint now has limits. It has to stay open to visitors
  — nobody logs in before being tracked — which made it the one part of the plugin a
  stranger could reach on your server, and it stored whatever it was sent. It now refuses
  oversized requests, caps what one event may keep, and limits how much any single
  address can write in a minute.
* A throttled caller is still told whether it is blocked. The limit is on writing, never
  on protecting.
* Event types are now a closed list, so nothing arbitrary can be written into your
  reports.

= 6.3.1 =
* The Get ClickHelm Pro link was breaking across two lines mid-phrase in the narrow plugin
  name column. It now moves to the next line whole.

= 6.3.0 =
* A Settings link under the plugin name on the Plugins screen, where everyone looks for it
  first.
* A Get ClickHelm Pro link beside it, which disappears once the licence is active.

= 6.2.1 =
* The mark in the page header was being drawn at the one size it is not meant to be drawn
  at, which closed up its spokes. Slightly larger, and correct.

= 6.2.0 =
* Fixed the page title in the plugin header, which had been painted in dark body text on a
  dark background since 5.1.0. It is now brass, which is where the brand signs its name.
* Added a way to reach the plans from the trial notice, from any paused screen, and from the
  Licence page when no key has been entered.

= 6.1.0 =
* **This version starts your recorded data fresh.** Everything the plugin stores is keyed on
  an internal name, and that name changed with the rest of the rebrand: visitors, events,
  blocks, settings and device fingerprints all begin again from zero. Blocking, tracking and
  every screen work exactly as before — there is simply nothing in them on day one.
* Before installing, delete the old plugin with **"Also erase everything this plugin stored"**
  ticked on its Settings → Housekeeping screen. Otherwise the old tables stay behind, taking
  up space and doing nothing.
* The Google Ads tracking template changed with it. Copy the new one from
  **ClickHelm → Google Ads → Setup & names** and paste it into Google Ads again.
* If your site calls `window.acsTrackConversion(...)`, it is now
  `window.clickHelmTrackConversion(...)`.

= 6.0.0 =
* Ad Click Shield is now **ClickHelm**. New name, new mark, new colours.
* Old screen addresses still work — anything bookmarked redirects to where it lives now.

= 5.14.0 =
* Licensing, with a seven day trial
* A lapsed licence never removes protection: everyone already blocked stays blocked and
  the plugin keeps watching. What stops is blocking anyone new — including someone you
  blocked before who returns on a different network, who is identified and shown to you

= 5.12.0 =
* Proper date ranges everywhere — today, yesterday, last 7/14/30/90 days, this month,
  last month, or a custom range
* Comparison is now a choice rather than forced, including against last year
* The picker states which days it counted, since "last 7 days" means different things in
  different tools

= 5.11.0 =
* Rebuilt the dashboard around spend, revenue and profit rather than counts
* A live feed of the most recent arrivals

= 5.10.0 =
* Heatmaps, with clicks anchored to the element they landed on, so points stay correct
  after the page is redesigned
* Rage-click detection

= 5.9.0 =
* Dismiss visitors from the dashboard list, reversibly — they return if their risk climbs
* Possible Duplicates moved inside Visitors

= 5.8.0 =
* Uninstall now cleans up after itself, but only if you ask it to first

= 5.7.0 =
* Google Ads is now one tab covering setup, campaigns, keywords, placements, repeat
  clickers and exclusion lists
* Campaigns and ad groups can be given readable names, since Google only sends numbers
* Cost per click can be set per campaign, so profit is measured on both sides
* Captures placement, ad and location, and recovers them from existing history

= 5.6.0 =
* Custom rules: your own conditions, with four actions including instant email alerts
* Alerts are batched per window rather than sent one at a time

= 5.5.0 =
* Weekly and monthly email reports
* The block page now records when it fires, so spend protected became a measured figure

= 5.4.0 =
* Rebuilt reports with period-over-period comparison, trends and drill-down

== Upgrade Notice ==

= 5.14.0 =
Adds licensing with a seven day trial. Existing blocks are never affected by a licence
lapse — this release cannot leave your site unprotected.
