=== Kehai Analytics ===
Contributors: kehai
Tags: analytics, woocommerce, privacy, ecommerce
Requires at least: 6.5
Tested up to: 7.1
Requires PHP: 8.1
Stable tag: 0.1.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

WordPress web analytics with an optional WooCommerce confirmed-payment and refund adapter.

== Description ==

One plugin, two independently enabled functions:

* WordPress tracker: public site ID and the site's full configured query exclusion list. No commerce secret is needed.
* WooCommerce: server-side order aggregates, recorded only after payment confirmation, with a durable delivery queue.

A Kehai account and site are required. No Google Ads or Stripe account is connected by this plugin. Google Ads exports in Kehai require a real payment time and a retained GCLID in the explicitly supplied purchase context.

== Installation ==

1. Upload kehai-wordpress.zip through Plugins > Add New > Upload Plugin, then activate.
2. Open Settings > Kehai Analytics. Enter the public site ID from Kehai Settings > Install.
3. Enable WordPress tracker. Query exclusions are managed only in Kehai Settings > Site and arrive with the tracker response; there is no list to paste. Remove an older manual snippet when moving to the plugin and clear HTML/page caches once after updating the plugin or changing the site ID.
4. For commerce, activate WooCommerce, enable Ecommerce on the Kehai site, and create its dedicated WordPress/WooCommerce integration key. Enter the secret in Commerce API key and select WooCommerce.
5. Save and check connection verifies the site, domain, commerce permission and enabled module. It refreshes the server-side commerce exclusion snapshot. It does not create a test sale.
6. Confirm a real successful payment through your payment method and check the delivery ledger. Configure regular WordPress cron for shops with low traffic; monitor Pending and Review.

Browser exclusion changes apply on the next tracker load after the collector refreshes its settings cache, within 30 seconds. Already-open pages keep their loaded settings. No HTML cache purge is needed for subsequent Kehai exclusion changes. Server-side commerce capture keeps the latest successful connection-check snapshot; the collector reapplies current site exclusions before storing orders.

Network activation is not supported. Activate separately for each site in a WordPress network, with its own site-scoped connection and queue.

== What counts as a payment ==

The automatic hook is WooCommerce payment_complete, using its actual date_paid. Creating an order, viewing a thank-you page, or changing a status to processing is not enough. In particular, cash-on-delivery may be processing before cash is received.

For bank transfer, cash-on-delivery, or gateways that do not call payment_complete, use Confirm a manual payment or refund. Enter the local order ID, actual payment timestamp with an explicit timezone, and confirm that the money was received. For example: 2026-09-13T14:30:00+02:00. The same local source is used for manual and automatic confirmation, so a later callback does not add the sale again.

Only future payment hooks are collected automatically. Enabling the plugin does not backfill old orders. Manual confirmation is an explicit request to include that transaction; use it only for the correct site and avoid historical orders already sent by another integration.

== Refunds and amounts ==

Product net excludes tax and shipping and already includes discounts. Unit price is before discount; item discount covers the whole line. Taxes and shipping are sent separately, using WooCommerce's actual amounts. Only catalogue SKU/product ID and product name are sent; personalised order line names, customer details, payment IDs and arbitrary order metadata are excluded.

Automatic refunds require WooCommerce's successful gateway refund marker. A manually recorded accounting refund needs explicit confirmation that money was returned; enter its local refund ID in the confirmation form. A refund waits for its purchase's successful Kehai delivery.

Complete refunds reverse the exact original breakdown. Itemised partial refunds reverse the specified quantities, tax, shipping and proportional original line discounts. A shipping/tax-only refund with an explicit complete breakdown is supported. An amount-only partial refund is supported only when tax, delivery and discount allocation are unambiguous; no product units are inferred.

Fee lines, fractional quantities, deleted catalogue products, mismatched totals and ambiguous partial-refund allocations enter Review instead of guessing a number. Correct an unattempted mapping in WooCommerce and confirm it again; its original random delivery UUID remains. A payload that was already prepared or attempted cannot be edited or resent under a new identity through this plugin.

A local hash of the original financial/catalogue basis also prevents a later order edit, SKU/name change or changed coupon-reporting selection from creating a refund against different product data. Such refunds enter Review. The hash does not contain the acquisition URL.

Coupon reporting is opt-in. Enable it only for public campaign codes that cannot identify a customer. One redeemed code can populate the coupon dimension; several codes are not combined into an invented code. Their actual discount amount is still reported.

== Attribution and privacy ==

The tracker does not add cookies or browser storage. Administrator visits, WordPress previews and browser DNT/GPC opt-outs are excluded. Existing Kehai scripts take precedence to prevent a second injection.

The optional WooCommerce adapter stores the first available page context in an already existing WooCommerce session. It does not create that session's cookie to recover an earlier landing. If a buyer first arrives before the shop has a session, that earlier context may be unavailable; it is not reconstructed. Checkout/account routes are not used as landing context.

The available site-relative URL and query are bounded to 2048 bytes, and query names/values to 255 characters. Only the site's configured exclusion list filters query names; there is no additional fixed UTM or GCLID whitelist. Referrers are reduced to a hostname. DNT/GPC prevents storing the context and marks the checkout order so later server payment callbacks remain excluded. It does not link orders to Kehai visitor IDs.

Session context older than two days is not copied to a new order. The captured context on an order is eligible for at most 90 days; hourly bounded cleanup removes older order context. WordPress cron delays can delay physical cleanup, so configure a reliable server cron. The accepted outbox payload is cleared immediately. Pending/review payloads are cleared within 48 hours by the queue's scheduled cleanup. Minimal local delivery records remain to prevent future duplicate callbacks. WooCommerce's order erasure removes stored context.

Collect only URLs, catalogue labels and public coupons appropriate for your installation. Unblocked click parameters may be linkable to advertising records. This plugin does not establish your legal basis, substitute for required consent, or provide a blanket GDPR certification.

== External services ==

The plugin sends data to the site's Kehai account at https://stats.kehai.io:

* GET /k.js?site=<public-site-id>: the browser loads the Kehai tracker with its current Settings. The tracker sends the page and declared event data described by https://kehai.io/docs/install and the selected site's settings.
* GET /api/v1/commerce/status: a server-side Bearer-key connection check returns site/module/query-exclusion configuration.
* POST /api/v1/commerce: server-side confirmed order aggregates, optional bounded acquisition context and a random idempotency UUID. The secret, local order/customer IDs and payment transaction IDs are not part of the analytics payload.
* POST /api/v1/commerce/status: at most once per minute, server-side pending/review counts and a fixed error category. No order identifier or raw error text is sent.

Commerce keys stay in a non-autoloaded WordPress option. They are never echoed in HTML, copied into JavaScript, or stored in the outbox. Protect database backups like other WordPress credentials. Outbound commerce requests require HTTPS, certificate validation and no redirects.

Kehai terms: https://kehai.io/terms-of-use
Kehai privacy: https://kehai.io/privacy-policy
Commerce contract: https://kehai.io/docs/ecommerce

== Queue operations ==

The local source ledger has one record per purchase/refund and a persisted random UUID. Retries keep the same key, UUID and frozen bytes. A lost response is uncertain, not evidence that the server stored nothing. Retry attempts stop within 47 hours of their first attempt, before the collector's 48-hour reservation expires. An expired or conflicting delivery needs reconciliation and is never automatically recreated.

Changing the site or API key is blocked while Pending or Review records exist. Retry pending delivery advances a pending attempt without changing its identity. Stop automatic delivery preserves the local source ledger; it cannot undo an already accepted sale. Reconcile any uncertain outcome before replacing the integration.

Deactivation stops scheduled work and retains settings/ledger. Uninstalling deletes local plugin settings, queue and order context; it does not delete already collected Kehai data. Reconcile unresolved deliveries before uninstalling, and do not replay historical confirmations after reinstalling without checking earlier deliveries.

== Compatibility ==

Uses WooCommerce order CRUD and supports HPOS and legacy order storage. Both classic checkout and the Store API checkout hook attach context. Compatibility depends on the gateway emitting payment_complete for actual receipt and correctly marking successful refunds. No checkout template replacement is needed.

== Changelog ==

= 0.1.1 =
* Site-specific tracker URL loads current Kehai settings without copied query exclusions. Recognizes both short and legacy manual tags to prevent duplicate tracking.

= 0.1.0 =
* Initial tracker and optional WooCommerce payment/refund integration, guarded connection setup, durable delivery queue and operational status.
