RockHeron

Description

Your ad platform counts its own results. RockHeron counts them on your site and
puts the two numbers next to each other.

It records which campaign introduced every form submission and every WooCommerce
order, in your own database on your own hosting, then shows what the platform
claimed beside what your site actually recorded, so you can see the gap rather
than take a dashboard’s word for it.

Lead source attribution

  • First touch attribution: the campaign that introduced a visitor is remembered for thirty days, and the first one keeps the credit
  • Source, medium, campaign, term and content, plus which parameter identified them
  • Six form plugins: Contact Form 7, WPForms, Gravity Forms, Elementor Forms, Fluent Forms and WooCommerce
  • WooCommerce orders, read from WooCommerce’s own order attribution rather than collected twice
  • A leads table of every submission with the campaign behind it, broken down by source, medium and campaign

What else it records on your site

  • Visits, visitors and page views, with the previous period next to every number
  • Goals: calls, emails, WhatsApp clicks, form sends, add to cart, or any element you name
  • Clicks on any element you name by CSS selector, site wide or on chosen pages
  • Elements seen on screen, video plays, scroll depth, outbound clicks, downloads, site searches
  • Where visits come from: search, AI assistants, social, referral, campaigns, direct
  • Devices, browsers, operating systems, countries, landing pages, top pages
  • A live count of visitors in the last thirty minutes

Google data next to it

  • Google Site Kit is used automatically when installed, so you do not connect Google twice
  • Without it, connect Analytics 4 directly using your own Google Cloud OAuth client
  • Search Console clicks, impressions, CTR and average position when Site Kit is present
  • Import past months from Google Analytics so the dashboard is not empty on day one
  • Import sixteen months of Search Console history, by button with Site Kit or from the export file without
  • Export any period as a CSV or an Excel file, with every card the site can produce and the results themselves in it, not just the cards left switched on
  • The Leads screen has its own export, carrying that screen and nothing else
  • Open a printable report the browser saves as a PDF, with the caveats carried into the file

Privacy

  • No analytics cookies, and no IP address is ever stored
  • The one cookie it does set is first party and holds campaign details only: no name, no email address, no telephone number, nothing typed into your form, no advertising click identifier
  • Visitors are counted with a one way hash that changes daily
  • Do Not Track and Global Privacy Control are respected
  • Works with CookiePile, the WP Consent API, or any consent cookie you name
  • Raw events are cleared on your own retention schedule while daily totals keep the history

Languages

Fully translated into Hebrew, with a right to left layout. The translation is
delivered by WordPress.org as a language pack rather than bundled in this zip,
which is why languages/ holds only the POT file: a bundled catalog would
shadow the pack and stop you receiving corrections. Any other language can be
added from that POT file, or contributed at
https://translate.wordpress.org/projects/wp-plugins/rockheron/

External services

RockHeron contacts nothing on its own. Every connection below happens only
because you connected an account or switched a setting on.

Google OAuth, Analytics 4 and Google Ads (optional, off until you connect them)

If you choose to connect Google directly, with your own Google Cloud OAuth
client, the plugin talks to Google from your server to read your own reports:

  • accounts.google.com – where your browser goes to approve the connection. Nothing is sent there by the plugin; you sign in to Google yourself.
  • oauth2.googleapis.com – exchanges the approval for an access token and refreshes it later. Sends your own OAuth client ID, client secret and the token.
  • analyticsdata.googleapis.com and analyticsadmin.googleapis.com – reads your Analytics 4 reports and property list. Sends the access token, the property ID and the date range and dimensions being requested.
  • googleads.googleapis.com – reads campaign spend and clicks, and only when you have entered a Google Ads customer ID and a Google approved developer token. Sends the access token, the developer token and the customer ID.

These four read your figures in. Nothing recorded about your visitors or your
leads goes out through them: no visit, no lead, no form entry, no email
address, no name, no IP address. That covers these four connections only, not
the Google tag below, which does send visitor data to Google.

With Google Site Kit, RockHeron reads through Site Kit on your own site and
makes no connection of its own.

Google tag (optional, off by default, and it does send visitor data to Google)

This runs in your visitors’ browsers, not on your server, and it is the
ordinary Google tag. Switch on “Inject the Google tag”, enter a measurement ID,
and every page your visitors load fetches
https://www.googletagmanager.com/gtag/js and reports to Google on their
behalf.

Google receives what the Google tag always receives: the page and its title,
the referring page, the visitor’s IP address, their device, browser, operating
system and screen size, their approximate location from that IP address, and
whatever Google’s own cookies on that browser already identify. RockHeron does
not choose or limit any of it. It places the tag and Google does the rest.

Because of that:

  • It is off by default and nothing is requested from Google until you turn it on.
  • It is skipped entirely when Site Kit or another plugin is already tagging the same property, so nobody is double counted.
  • It is not loaded until the visitor has allowed it. Consent and Do Not Track are evaluated in the visitor’s own browser, so a cached page cannot serve one visitor’s answer to the next. With a consent mode set, no request reaches Google before that visitor consents, and if they consent later on the same page the tag loads then.
  • Turning it on is a decision about your visitors’ data, not just your own reporting, and your privacy policy should say so.

These are Google services, governed by the Google Privacy Policy
(https://policies.google.com/privacy), the Google APIs Terms of Service
(https://developers.google.com/terms) and, for Analytics data, the Google
Analytics terms
(https://marketingplatform.google.com/about/analytics/terms/us/).

Nothing else

RockHeron contacts no service of ours, phones no home, and loads no script or
stylesheet from a CDN. Everything it ships runs from your own server, including
the bundled charting library below.

Third party credits

Chart.js 4.6.1, MIT licensed, bundled at assets/vendor/chartjs/. The
dashboard and report charts are drawn with it. Its license is in
assets/vendor/chartjs/LICENSE.md and the source is at
https://github.com/chartjs/Chart.js/tree/v4.6.1

Nothing else is bundled.

Screenshots

Installation

  1. Upload the plugin folder to /wp-content/plugins/, or install the zip from Plugins, Add New.
  2. Activate it.
  3. Open RockHeron. Visits start appearing within a minute.
  4. Optional: open Settings to connect Google, or install Site Kit and it is picked up on its own.

FAQ

Do I need Google Analytics for this to work?

No. Everything on the dashboard except the GA4, Search Console and Ads cards comes from your own site.

Will it slow my site down?

The tracking script is roughly 6 KB, loads in the footer, and sends one small beacon per page view. Reports read a pre built daily table rather than scanning raw rows.

Does it work with caching plugins?

Yes. Page views are counted in the browser, so a cached page is still recorded.

The dashboard is empty, where is my history?

The plugin starts recording the day you install it. Open Settings, Import
history from Google Analytics, and it fills the earlier months from your GA4
property. Imported days are dashed on the chart because Google counts sessions
slightly differently.

I took the site over and the old analytics account is not mine

Import your Search Console history instead. Settings, Import search history from
Search Console, upload the export file. It needs no Google connection, because
the site owner always has their own Search Console property even when the
analytics account belongs to a previous agency.

How do I track a specific button?

Open RockHeron, Tracked elements. Give it a name, paste the button’s CSS selector, and tick “count this as a goal” if it matters commercially.

How do I set it up, screen by screen?

Nothing here needs an account anywhere unless you choose to connect Google.

First run, and the screens

  1. Activate the plugin and open RockHeron. Recording starts immediately and
    the first visits appear within a minute. There is nothing to switch on.
  2. Dashboard is traffic: sessions, daily visitors, page views, goal
    completions and conversion rate, each against the previous period, with cards
    for where visits came from, top pages and traffic over time.
  3. Leads is the point of the plugin: every form submission and WooCommerce
    order with the campaign that introduced the person, read as first touch. A
    result nobody could attribute is listed as Not known rather than dropped, so
    these totals never quietly disagree with your form plugin.
  4. Tracked elements counts anything you name with a CSS selector: a quote
    button, a telephone link, a PDF download. Tick “count this as a goal” and it
    feeds the conversion figures.
  5. Settings holds Google, privacy, retention and the Google tag.

Form plugins are read automatically, never written to. Contact Form 7, WPForms,
Gravity Forms, Elementor Forms, Fluent Forms and WooCommerce are supported, both
WooCommerce checkouts included, and the Leads screen lists which it can see, so
an empty screen tells you why it is empty.

Google: what it is for, and what you need

You do not need Google at all. The plugin records visits and leads from
your own site, in your own database. Connecting Google only adds Google’s own
numbers beside yours. Three independent things:

  • Google Analytics 4 reporting. Settings, Google data. Either install Site
    Kit by Google and RockHeron uses its connection, or connect directly. A direct
    connection needs a Google Cloud project with the Analytics Data API enabled
    and an OAuth client of type Web application, whose Client ID and Client secret
    you paste into Settings. The scope is analytics.readonly, read only: nothing
    is written back and no visitor data is sent.
  • Google Ads. Only if you switch it on, adding the adwords scope to the
    same connection so spend and clicks can be read.
  • Search Console history. No API, no credentials. Export the Performance
    report from Search Console and upload the zip, or the CSVs inside it, in
    Settings.

The Google tag is separate again and off until you enter a measurement ID.
It is the ordinary gtag.js, so switching it on sends Google what the Google tag
always sends: page views, device and IP address, under Google’s terms rather
than ours. The reporting connections above send Google nothing. Leave the field
empty and no tag is loaded.

Campaigns (Pro)

The paid version adds a Campaigns screen that takes a CSV of what each platform
claimed, and shows it beside what this plugin recorded. The column format is
documented at https://rockheron.com/documentation/

Consent, and Do Not Track

Settings, Privacy. Consent mode is off by default, which records every
visit. The other three modes are:

  • WP Consent API, for any consent plugin implementing it. Statistics
    consent is required before anything is recorded.
  • CookiePile, read directly.
  • A cookie you name: give the cookie name and the value meaning consent.

Where a mode is selected but cannot be evaluated, for example the consent plugin
has been deactivated, the plugin fails closed and records nothing.

Consent and Do Not Track are evaluated in the visitor’s browser, not on the
server, because a decision made in PHP is written into your page cache and then
served to the next visitor, whose answer may be the opposite. Respect Do Not
Track is a separate switch in the same panel. Somebody who accepts after the
page has loaded is picked up without a reload.

What is stored, how long, and how to delete it

What is kept about a lead is the campaign and a pointer to the form plugin’s own
entry. No name, no email address, no telephone number, and no advertising
click identifier.
Your form plugin already holds the submission, and a second
copy of every lead on your site is a duty rather than a feature.

Three retention settings, all in Settings, Stored data:

  • Attribution window, default 30 days. How long the first touch campaign is
    remembered in one first party cookie. 1 to 365.
  • Raw events, default 90 days. Individual page views are pruned nightly
    after this; the daily totals they roll up into are kept.
  • Leads, default 400 days. 30 to 3650.

To remove everything: Settings, Stored data deletes recorded data without
uninstalling. Uninstalling with “delete my data” on drops every table, option,
transient and scheduled job the plugin created, found by prefix rather than from
a list. Deactivating removes only the scheduled jobs, so your data survives an
update.

How the lists are stored

Lists like top pages, referrers, campaigns and landing pages are rolled up once
a day. Each day keeps its busiest rows by name and sums the rest into a single
“everything else” figure, so the stored rows account for the whole day however
long the list.

The totals are right either way. A cap changes only how much of the long
tail is broken out by name: a page ranking below it every day is still counted,
inside that one figure rather than under its own address.

Defaults are 200 rows a day for pages and landing paths, 100 for referrers,
campaigns, outbound links and searches, and 50 for lists that cannot produce
more anyway, such as device, browser and country. Settings, Stored data has
one field, “Rows kept per list, per day”
, setting a single number for every
list; zero, the default, leaves each on its own. The rockheron_dim_limit
filter takes ( $limit, $dim ) to raise one list without the rest.

Each extra row is kept for good, since the daily totals outlive the raw events
behind them, so raising this on a site with thousands of URLs costs table rows
for every day the site runs.

Troubleshooting

  • The dashboard is empty. The plugin knows only what it has recorded since
    activation; it cannot see the past. Check you are not logged in as an
    administrator or editor: those roles are excluded by default, in Settings,
    What to record, so browsing your own site while logged in deliberately
    records nothing.
  • Nothing appears on a cached site. Recording runs in the browser and does
    not need an uncached page. If you see nothing, check your caching or
    optimization plugin is not deferring or stripping the script.
  • Leads are missing. The Leads screen lists the form plugins it can see. If
    yours is absent it is not supported yet. If it is listed but entries are not
    arriving, confirm the form completes: a submission that fails validation is
    not a lead.
  • Google numbers will not load. Reconnect in Settings, Google data. An
    expired or revoked connection reports the error it received rather than
    showing zero, because zero is a real figure and a broken connection must not
    produce one.
  • Figures disagree with Google. They will, always, and neither is wrong.
    Google counts sessions its own way and loses what consent and ad blockers
    take; this plugin counts what reached your database. Both are shown, never
    reconciled.

Support

  • Documentation: https://rockheron.com/documentation/
  • Support: https://rockheron.com/support/
  • Email: support@rockheron.com

Bring us the problem whichever route you bought by. Quote your license key if
you have one; otherwise the site address is enough.

Reviews

There are no reviews for this plugin.

Contributors & Developers

“RockHeron” is open source software. The following people have contributed to this plugin.

Contributors

Translate “RockHeron” into your language.

Interested in development?

Browse the code, check out the SVN repository, or subscribe to the development log by RSS.

Changelog

1.1.0

  • Exports now carry everything the site knows, not the part that happened to be on screen. The file used to be built from the cards you had switched on, so a card you had hidden could not be exported at all even though the figures were sitting in the same table. Hiding a card is a decision about a screen, not about what the site knows.
  • Your results are in the export. The plugin is called lead source attribution and the one thing you could not get out of it was the leads. Every result in the period is now in the file, with its campaign, its channel, where it landed, what it was worth and what the source was worked out from.
  • An Excel export, next to the CSV. Figures arrive as figures, so you can sort and total them, and a campaign named =1+1 arrives as text rather than as something your spreadsheet tries to calculate.
  • The Leads screen has its own CSV and Excel, separate from the dashboard’s. It carries that screen and nothing else: the headline figures, the four ways of cutting them, and the results themselves. The file is named after the screen it came from, so the two do not land in your downloads folder as copies of each other.
  • All three formats are built from one description of the report, so a figure you read on screen, a figure in the spreadsheet and a figure in the PDF cannot come to disagree.
  • Every string the new screens and files use is translatable, and the Hebrew is included.
  • Paid builds now produce a real PDF rather than a printable page. It is laid out for the page: a running footer with page numbers, a table heading that repeats when a table runs over a break and says what it is, the results on a landscape page of their own, and the day by day figures drawn as a line. Scheduled reports arrive with that PDF attached instead of a file to open and print. Hebrew sites get a right to left report, with page paths, campaign tags and search terms printed the way round they were recorded.
  • The PDF shows the newest 500 results and the 100 largest rows of each breakdown, and says so under each table. It is a document to read and hand over, and a report of several thousand rows is hundreds of pages that most servers will not finish building. The CSV and the Excel file are not limited and carry everything.
  • A campaign could still be attached to a form submission after the visitor had withdrawn consent. The browser stops measuring the moment consent is withdrawn, which was working, but the cookie it had already written keeps being sent with every later request, and the plugin was still reading it when a form was submitted. So somebody who accepted your banner, was tagged by a campaign, then changed their mind, still had that campaign copied onto their next inquiry. Do Not Track and Global Privacy Control had the same gap from the other side: they stopped the cookie being written and never stopped an existing one being read. The same was true of the source WooCommerce records for an order, which is a separate route to the same information.
  • Consent and Do Not Track are now checked before any campaign detail is read, on every route a visitor’s own request can take. The submission is still recorded, with no campaign on it, and appears as Not known, so your totals still match your form plugin’s. Importing past orders from the Settings screen is unaffected: that is you asking, over orders WooCommerce already attributed, and it is not a visitor request.

Earlier releases

1.0.0 was the first public release. 0.1.0 through 0.9.9 were development
releases: the plugin was not published anywhere while they were being written,
so no site ever ran that code. The release history from 0.6.0, with the
reasoning behind each decision, is at https://rockheron.com/changelog/