=== AdPix Analytics ===
Contributors: adpixteam, mohsenhasanpour
Tags: analytics, attribution, woocommerce, conversion tracking, statistics
Requires at least: 5.8
Tested up to: 7.1
Requires PHP: 7.4
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

Adds the AdPix tag to WordPress and reports WooCommerce orders, sign-ups and leads server-side, so conversions count even without the browser.

== Description ==

AdPix Analytics connects your site to an [AdPix](https://adpix.io/) property. It does two things, and the second is the one that matters.

The first is ordinary: it prints the AdPix measurement tag, so visits, campaigns and referrers are recorded in the browser.

The second is that it reports conversions **from your server**, over AdPix's server-to-server API. A browser-only tag misses a great deal — a purchase confirmed by a bank redirect, an order a shop manager marks paid two days later, a visitor running an ad blocker, a phone that closed the tab before the thank-you page loaded. Each of those is a real sale that browser-side measurement quietly loses. Reporting it from PHP, with the visitor's original acquisition attached, is the difference between a campaign that looks unprofitable and one you can see actually paid.

= What it measures =

* **WooCommerce** — orders, payment completion, status changes and refunds, with line items, currency and order value. Orders are reported once and only once, whatever path they took to being paid.
* **Registrations** — sign-ups and log-ins, linking a visitor's earlier anonymous browsing to their account.
* **Contact forms** — submissions to Contact Form 7, WPForms and Gravity Forms, reported as leads. The message body is never sent; only the contact details needed to match the lead to the visit that produced it.
* **Page views and campaigns** — through the standard AdPix tag.

= Built for shops that do not lose orders =

* **Attribution is captured at checkout, not at delivery.** An order paid three days later is still credited to the campaign that earned it, not to whoever happened to change its status.
* **Nothing is dropped when the network is.** Events go through a retry queue with exponential backoff, using Action Scheduler when WooCommerce provides it and WP-Cron otherwise.
* **Orders are reported exactly once.** Every event carries a stable identifier, so a retry, a double webhook or a manual status change cannot inflate your revenue.
* **The order screen shows where the sale came from** — channel, campaign, first touch, and how long the customer took to decide.

= Where the tag goes, and who it leaves out =

* **Head or footer.** The head measures visitors who leave quickly; the footer takes the tag off the critical path on a slow site.
* **Leave out your own team.** Tick the roles whose logged-in visits should not load the tag, so the people running the shop stay out of the reports.
* **Leave out particular pages**, by ID, and optionally search results and archive listings.
* **Measure the admin area too**, if you want it — off by default.

These affect page measurement only. An order placed by an excluded user is still reported from the server, because it is still a sale.

= Your statistics, without leaving WordPress =

**Site statistics** sits in the sidebar beside the settings. It reads back what AdPix has already measured — it collects nothing extra and stores nothing new on your site — and lays it out as:

* **Visits over time**, across the last 7, 28 or 90 days, this month or last month, with the numbers behind the chart available as a plain table for anyone using a screen reader.
* **Headline figures** — visitors, visits, page views, conversions and conversion value for the period.
* **Where your visitors are**, by country.
* **How they found you**, by channel, and your **most-read pages**.
* **What they were using**, by device.

Reading reports is a separate permission from sending measurements, deliberately so: the server key this plugin sends with can write to your whole property and is never allowed to read it. The statistics screen therefore needs a read-only API token of its own, created in your AdPix dashboard under **Admin → API & MCP → Service tokens**. Leave it empty and nothing else changes — the rest of the plugin works exactly as before.

= Simple and advanced mode =

The settings screen opens in **Simple** mode, which shows only what most sites need: the measurement ID, property ID, server key and API token, and what to measure. Switch to **Advanced** in the header for request signing, Force SSL, a custom API address, the visitor IP option, custom code and the list of recent delivery problems. Switching modes never changes a setting by itself: what Simple mode hides keeps the value it had.

The AdPix addresses are built in — `https://api.adpix.io` for server-to-server calls and reports, `https://cdn.adpix.net` for the tag script and `https://collect.adpix.net` for the browser's events — so there is nothing to copy for them.

= Custom code =

Available in Advanced mode.

* **Custom tag code** — JavaScript run immediately after the tag is set up, when `ap()` is ready.
* **Custom code** — markup printed on every page whether or not the tag is configured, for a verification tag or a third-party snippet, in the head or the footer.

Both code fields can only be changed by a user who is allowed to publish unfiltered HTML, which on a multisite network means a network administrator.

= Translations =

The plugin is written in English and fully translatable. Translations are hosted on [translate.wordpress.org](https://translate.wordpress.org/), and the settings screen is laid out with logical CSS properties so it reads correctly right-to-left without a separate stylesheet.

= Privacy and consent =

* Visitors who opt out of measurement are never reported, whatever the settings say.
* When your consent banner has recorded a choice, the plugin reads it and honours it. The consent decision applied to an order is the one the customer made at checkout.
* Sending the visitor's IP address is a setting you can turn off. It is what resolves the country and city of a conversion.
* The plugin adds a suggested section to WordPress's privacy policy tool describing exactly what leaves the site.

= Your server key never reaches the browser =

The server key can write to your whole AdPix property. This plugin never prints it into a page, never enqueues it to a script and never returns it from an AJAX call. The settings screen shows it masked. For the strongest arrangement, put it in `wp-config.php`, where no database backup can carry it:

`define( 'ADPIX_ANALYTICS_PROPERTY_ID', 'your-property-id' );`
`define( 'ADPIX_ANALYTICS_SERVER_KEY', 'sk_...' );`

Any setting defined this way is shown read-only in the admin and is never written to the database.

For a self-hosted AdPix or a first-party tag gateway, the built-in addresses can be replaced the same way: `ADPIX_ANALYTICS_COLLECTOR_URL` (server-to-server), `ADPIX_ANALYTICS_TRACKER_URL` (tag script) and `ADPIX_ANALYTICS_ENDPOINT` (browser events, which falls back to the collector URL when only that is set).

= WP-CLI =

`wp adpix status` — how many events are waiting
`wp adpix verify` — check the stored credentials against the collector
`wp adpix drain` — deliver the backlog without waiting for cron
`wp adpix purge --yes` — discard the queue

== External services ==

This plugin sends data to the AdPix service so that visits and conversions can be measured: `https://api.adpix.io`, `https://cdn.adpix.net` and `https://collect.adpix.net`, or your own self-hosted AdPix installation when its addresses are set in `wp-config.php`. **No data is sent anywhere until you enter a measurement ID, or a property ID and a server key** — an installed but unconfigured plugin makes no external requests at all.

**The measurement tag.** When a measurement ID is configured, each page loads a script from `https://cdn.adpix.net/t.js`, and the visitor's browser sends its events to `https://collect.adpix.net`. That script records page views and the campaign, referrer or advertising click that brought the visitor to the site, and stores them in first-party cookies so a later conversion can be credited correctly.

**Server-to-server reporting.** When a visitor places an order, registers, or submits a contact form, your server sends that event to the `https://api.adpix.io/api/v1/s2s/` endpoints. Depending on what happened and what the visitor provided, the request may include:

* the event name and a unique event identifier
* the email address and phone number given at checkout or on the form
* the order number, value, currency, status and line items
* the visitor's IP address and browser user agent (the IP can be turned off in the settings)
* the campaign, source, medium and referrer recorded in the visitor's first-party cookies
* for registrations, the WordPress user ID, display name and role

Message bodies from contact forms, passwords, and payment details are never sent.

**Reading attribution back.** On a WooCommerce order screen, the plugin asks `https://api.adpix.io` what it knows about that order, sending only the order number.

**Reading your statistics.** Only when you fill in the optional read-only API token, the **Site statistics** screen asks the AdPix reporting API at `https://api.adpix.io` for aggregate reports about your property: visit, visitor and page-view counts by day, country, channel, page and device. The request carries the property ID, the date range and that token, and nothing about any individual visitor or order. Results are cached on your site for ten minutes. Leave the token empty and the plugin never contacts the reporting API at all.

These services are operated by AdPix, or by you when self-hosted. For the hosted service, see the [AdPix terms of service](https://adpix.io) and [privacy policy](https://adpix.io). For a self-hosted collector, the terms are your own.

== Installation ==

1. Install and activate the plugin.
2. Go to **AdPix → Settings** in the sidebar.
3. Enter the measurement ID, property ID and server key from your AdPix property's install instructions. The AdPix addresses are built in.
4. Save, then press **Test the connection**. It will name the property you connected to.
5. Choose what to measure and, if you use a consent banner, leave **Only measure visitors who allowed it** switched on.

To see your figures in **AdPix → Site statistics**, add a read-only API token under **Connection → Reading your statistics**. This is optional and separate from everything above.

For WooCommerce, install [Action Scheduler](https://actionscheduler.org/) or simply keep WooCommerce active — it ships with it — so retries run on WooCommerce's queue rather than on WP-Cron.

== Frequently Asked Questions ==

= Do I need an AdPix account? =

Yes. The plugin connects an existing AdPix property to this site; it is not a standalone analytics tool. You can point it at the hosted service or at your own AdPix installation.

= Will this double-count my page views? =

No. The tag initialises with a single call that also records the first page view, rather than a separate init-then-track pair.

= Does it work with High-Performance Order Storage? =

Yes. Every order is read and written through WooCommerce's CRUD API, so both HPOS and the legacy post storage work, and the plugin declares compatibility with both HPOS and the cart and checkout blocks.

= What happens if the collector is unreachable? =

The event stays in the queue and is retried with a growing delay, for up to about seven hours. Nothing is reported to the browser and nothing blocks checkout: reporting happens after the order is already saved.

= Can I install the tag myself and still use server-side reporting? =

Yes. Turn off **Add the measurement tag to the site** and leave the rest configured.

= Does it respect my cookie banner? =

If your banner writes the standard consent cookie, yes — statistics and marketing categories are read separately, and a visitor who opted out is never measured. If no banner has recorded a choice, measurement proceeds, because "no banner" is not a refusal.

= How do I keep my own visits out of the reports? =

Under **Page tag**, tick your role — administrator, shop manager, or whichever you sign in as — beside **Do not measure**. Logged-in users holding that role will not load the tag. Orders those users place are still reported, because an order is a sale however it was placed.

= Can I put the tag in the footer? =

Yes, under **Page tag → Tag location**. The head is the default because it also catches visitors who leave before the page finishes loading.

= Can I change the tag settings the plugin generates? =

Yes, with the `adpix_analytics_tag_config` filter, which receives the configuration passed to the tag. In Advanced mode, **Custom tag code** also runs straight after the tag is set up.

= I changed too many settings. Can I start again? =

**Restore default options**, at the bottom of the settings screen, puts every option back the way it shipped. Your IDs, server key and API token are kept — those cannot be read back off the screen, so the button does not throw them away.

= Is the plugin available in my language? =

Every string is translatable, and translations are served from [translate.wordpress.org](https://translate.wordpress.org/) as they are contributed. Help with your own language is welcome there.

= Why does the statistics screen need a second credential? =

Because the first one cannot read. The server key sends events to your collector and can write to your whole property; letting a WordPress site read its own reports with it would mean a site compromise handed over far more than it needs to. A read-only API token, made under **Admin → API & MCP → Service tokens** in your AdPix dashboard, can fetch this property's reports and do nothing else.

= Do I have to use the statistics screen? =

No. Leave the API token empty and the screen simply explains how to connect it. Measurement and conversion reporting are unaffected either way.

= Where is the data stored on my site? =

In one option row for the settings, one for the retry queue, and one for the last twenty delivery failures. Two pieces of meta are stored per WooCommerce order: the visitor context captured at checkout and a marker recording that the order has been reported. No database tables are created.

== Changelog ==

= 1.0.0 =
* First release.
* Measurement tag injection with a single-call initialisation.
* Server-to-server reporting of WooCommerce orders, refunds, registrations and form leads.
* Checkout-time attribution capture, so delayed orders keep their original acquisition.
* Retry queue on Action Scheduler or WP-Cron, with idempotent event identifiers.
* Attribution panel on the order screen.
* Consent and opt-out handling, privacy policy text, and WP-CLI commands.
* Tag placement in the head or footer, optional measurement of the admin area, and exclusions by role, by post ID and for search and archive listings.
* Simple and advanced modes for the settings screen; the AdPix addresses are built in.
* Custom tag code and site-wide custom code, both gated on the `unfiltered_html` capability.
* Force SSL for addresses set in wp-config.php or the advanced API URL.
* Restore default options, keeping the connection details.
* Settings screen laid out as tabbed sections with a live status panel beside them.
* Top-level AdPix menu holding the settings and a Site statistics screen.
* Site statistics: visits over time, headline figures, countries, channels, pages and devices, read from the AdPix reporting API with a read-only token and cached for ten minutes.
* Admin screens responsive from a wide desktop down to a phone, with the charts and tables reflowing rather than scrolling sideways.
* Every string translatable, and a right-to-left ready admin.

== Upgrade Notice ==

= 1.0.0 =
First release.
