Docs/WooCommerce
WooCommerce
The script on the storefront, and the order recorded from PHP — so a sale counts even when the customer never comes back to the thank-you page.
1. The tracking script
WooCommerce runs on WordPress, so the install is the WordPress one: a must-use plugin, which survives a theme change. See the WordPress guide, or paste this file directly.
<?php
/**
* Plugin Name: Kipstats
* Description: Cookie-free analytics. Survives theme changes.
*/
add_action('wp_head', function () {
echo '<script defer src="https://kipstats.com/tracker.js" data-site="kp_xxxxxxxx"></script>';
}, 1);2. The ingest key, out of the repository
Recording an order is a write, so it needs the site's ingest key (kpi_…), found in Dashboard → your site → Settings. Put it in wp-config.php, never in a theme file and never in Git:
define('KIPSTATS_INGEST_KEY', 'kpi_your_ingest_key');3. The order, from PHP
woocommerce_payment_complete fires when the payment is confirmed — including when the gateway confirms it minutes later, with nobody's browser involved. That is exactly the case the browser cannot cover.
<?php
/**
* Plugin Name: Kipstats orders
* Description: Records a paid WooCommerce order as a Kipstats purchase.
*/
add_action('woocommerce_payment_complete', function ($order_id) {
if (!defined('KIPSTATS_INGEST_KEY')) {
return;
}
$order = wc_get_order($order_id);
if (!$order) {
return;
}
$paid_at = $order->get_date_paid();
wp_remote_post('https://kipstats.com/api/collect/server', [
'timeout' => 5,
'blocking' => false,
'headers' => [
'Authorization' => 'Bearer ' . KIPSTATS_INGEST_KEY,
'Content-Type' => 'application/json',
],
'body' => wp_json_encode([
'name' => 'purchase',
'ref' => 'wc_' . $order->get_id(),
'occurredAt' => $paid_at ? $paid_at->format('c') : null,
'data' => [
'amount' => (int) round($order->get_total() * 100),
'currency' => $order->get_currency(),
'items' => $order->get_item_count(),
],
]),
]);
});refis the order ID, so a gateway that retries does not create a second sale.'blocking' => falsekeeps checkout fast: WordPress does not wait for our answer. The trade-off is that a failure is silent — check one real order after installing.- Amounts are sent in the smallest unit. The
× 100above is right for euros, dollars and pounds, wrong for zero-decimal currencies such as JPY — adjust if you sell in one.
4. Optional: the steps before payment
The order tells you what was bought, not where people gave up. Two events on the storefront are enough to see the drop:
<script>
function kp(n, d) {
try { if (window.kipstats && window.kipstats.event) window.kipstats.event(n, d || {}) } catch (e) {}
}
// on the cart page, when the customer heads to checkout
kp('checkout_started', { price: <?= (int) round(WC()->cart->get_total('edit') * 100) ?>, currency: '<?= get_woocommerce_currency() ?>' })
</script>Rage clicks, dead clicks and abandoned fields on your checkout form are captured without any code — they are usually where the answer is. See what is captured automatically.
5. Check it once, for real
- Place one real order (or one in your gateway's live test mode, if it marks it as such — never emit a sale for a test payment).
- Open Events in your dashboard: a
purchaseshould be there, with the right amount and currency. - Refund or cancel your test order in WooCommerce. ⚠️ The refund is not deducted from Kipstats revenue today — see tracking revenue.