> ## Documentation Index
> Fetch the complete documentation index at: https://docs.davazmysel.com/llms.txt
> Use this file to discover all available pages before exploring further.

# WordPress & WooCommerce integration

> Install Dáva's browser listener and send server-side conversion events from WooCommerce order hooks.

This guide covers the most common WordPress integration: browser tracking via the theme `<head>` or Google Tag Manager, plus server events fired from WooCommerce's order completion hooks.

For the full server-event field reference, deduplication behaviour, and error codes, see [Server-Side Events](/tracking/server-side-events).

## Browser tracking

### Method 1 — Paste the snippet in your theme

Add the tracking snippet to the `<head>` of every page. The safest place is your **child theme's** `functions.php` via `wp_head`:

```php theme={null}
// In your child theme's functions.php:
add_action('wp_head', function () {
    ?>
    <script src="https://cdn.davazmysel.com/t.js" data-site="acct_a1b2c3d4" defer></script>
    <?php
});
```

Replace `acct_a1b2c3d4` with your workspace ID — copy it from the **Site ID** card under **Settings → Workspace → Settings & Integrations**, or from the full snippet on the **Tracking** tab. Always copy the ID from the dashboard rather than retyping it. Use a child theme so the snippet survives parent-theme updates. Alternatively, use a plugin that injects code into `<head>` (e.g. WPCode).

### Method 2 — Google Tag Manager Custom HTML tag

If your site is managed through GTM:

1. Create a new **Custom HTML** tag in GTM.
2. Paste the snippet into the HTML field.
3. Set the trigger to **All Pages**.
4. Publish the container.

<Warning>
  **GTM can strip `data-*` attributes.** If the **Support document.write** option is disabled on your Custom HTML tag (the default), GTM may remove the `data-site` attribute before injecting the script. Without `data-site`, the snippet does not know which workspace to report to and sends no data.

  **Fix:** Open the Custom HTML tag settings and enable **Support document.write** — this preserves the full script tag including `data-site`.
</Warning>

## Server events

### WooCommerce order completion hook

Send a `conversion` event when WooCommerce confirms payment. Add this to your child theme's `functions.php` or to a site-specific plugin:

```php theme={null}
<?php
add_action('woocommerce_payment_complete', function (int $order_id): void {
    $order = wc_get_order($order_id);
    if (!$order) {
        return;
    }

    // Retrieve the Dáva session ID stored during checkout
    // (see Hybrid setup below for how to collect and store it).
    $dava_session_id = $order->get_meta('_dava_session_id') ?: null;

    $hashed_email = hash('sha256', strtolower(trim($order->get_billing_email())));

    $payload = wp_json_encode([
        'subdomain'       => 'yourcompany.com',   // your Dáva-registered domain
        'event_type'      => 'conversion',
        'event_name'      => 'purchase',
        'hashed_email'    => $hashed_email,
        'contact_id'      => $order->get_customer_id()
                               ? (string) $order->get_customer_id()
                               : null,
        'dava_session_id' => $dava_session_id,
        'event_id'        => 'order_' . $order_id,
        'transaction_id'  => (string) $order_id,
        'value'           => (float) $order->get_total(),
        'currency'        => get_woocommerce_currency(),
    ]);

    wp_remote_post('https://api-v2.davazmysel.com/v1/events', [
        'headers' => [
            'Authorization' => 'Bearer dava_sk_live_xxxxxxxxxxxxxxxxxxxx',
            'Content-Type'  => 'application/json',
        ],
        'body'    => $payload,
        'timeout' => 10,
    ]);
});
```

<Note>
  At least one of `anonymous_id`, `contact_id`, or `hashed_email` is required. For guest checkouts, `contact_id` may be empty — `hashed_email` alone is sufficient. Include both when available for stronger identity matching.
</Note>

<Note>
  `subdomain` is required when calling `api-v2.davazmysel.com` directly. If you have configured a custom domain in Dáva (your own hostname registered in **Domain Settings**), omit `subdomain`. See [Sending a single event](/tracking/server-side-events#sending-a-single-event) for details.
</Note>

`event_id` and `transaction_id` are dedup keys — see [Deduplication](/tracking/server-side-events#deduplication) for the full priority chain. Use `properties` for any additional domain-specific facts (e.g. `properties.sku`, `properties.plan`).

`woocommerce_payment_complete` fires once payment is confirmed by the payment gateway. If you also need to fire on manual order status changes, use `woocommerce_order_status_completed`:

```php theme={null}
add_action('woocommerce_order_status_completed', function (int $order_id): void {
    // Same body as above — fires on both gateway confirmation and manual status change.
});
```

## Hybrid setup (recommended)

A hybrid setup links the server conversion event to the visitor's browser journey, attributing the purchase to the campaign that brought them in rather than storing it as an unmatched server event.

**The flow:**

1. Your checkout page loads the Dáva snippet, which creates a browser session.
2. Your **checkout page JavaScript** reads the session ID: `window.dava.sessionId`
3. JavaScript writes the value into a hidden form field that posts with the checkout form.
4. PHP reads the value from `$_POST` and saves it to the WooCommerce order as custom meta.
5. The `woocommerce_payment_complete` hook reads the meta and includes it as `dava_session_id` in the server event.

**Step 1 — Inject the session ID into the checkout form (JavaScript):**

```js theme={null}
// On the checkout page — runs after the Dáva snippet has loaded:
document.addEventListener('DOMContentLoaded', function () {
  var sessionId = window.dava ? window.dava.sessionId : null;
  if (!sessionId) return;

  var field = document.getElementById('dava_session_id');
  if (field) field.value = sessionId;
});
```

**Step 2 — Add the hidden field to the WooCommerce checkout form (PHP):**

```php theme={null}
add_filter('woocommerce_checkout_fields', function (array $fields): array {
    $fields['order']['dava_session_id'] = [
        'type'    => 'hidden',
        'default' => '',
    ];
    return $fields;
});
```

**Step 3 — Save the value to order meta when the order is created (PHP):**

```php theme={null}
add_action('woocommerce_checkout_create_order', function (WC_Order $order, array $data): void {
    $session_id = sanitize_text_field($_POST['dava_session_id'] ?? '');
    if ($session_id !== '') {
        $order->update_meta_data('_dava_session_id', $session_id);
    }
}, 10, 2);
```

The `woocommerce_payment_complete` hook then reads `_dava_session_id` from the order meta (as shown in the Server events section above) and passes it as `dava_session_id` in the event payload.

<Warning>
  **PHP cannot read `window.dava.sessionId` directly** — that is a browser object. Your frontend JavaScript must collect it and pass it to PHP explicitly via a form field, cookie, or AJAX request. The PHP hook reads it from wherever the frontend placed it.
</Warning>

For more on journey joining and what happens when the session ID does not match, see [Joining the visitor's journey](/tracking/server-side-events#joining-the-visitor-s-journey).

## Next steps

* [Server-Side Events reference →](/tracking/server-side-events) — full field table, dedup chain, batch endpoint, and error codes
* [Install the tracking snippet →](/tracking/install-snippet) — snippet options, consent mode, and the Cloudflare Worker proxy install method
