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

# Analytics with self-hosted Matomo in Vulpy

> Run consent-gated behavioral analytics with self-hosted Matomo in Vulpy Commerce: optional in dev, required to go live, and privacy-first by default.

Vulpy Commerce ships self-hosted Matomo as the behavioral analytics stack for your storefront. It is consent-gated at the storefront edge, optional locally, and required to go live. Order lifecycle reporting is separate and runs through Medusa without visitor consent.

<Tip>
  **Ask Fox to check Matomo.** Fox can tell you if it's up, add events, and diff dev vs. staging tracking.

  Try prompts like:

  * "Is Matomo running on dev?"
  * "Add a Matomo event for the newsletter signup CTA."
  * "Which events are firing on the homepage right now?"
</Tip>

## Environments

| Environment | Matomo                                                                                                                                                  |
| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
| dev         | Optional. Start with `pnpm db:matomo:up`; stop with `pnpm db:matomo:down`.                                                                              |
| live        | Required. `pnpm vulpy env up live` runs `setup-matomo.sh`; `pnpm vulpy env golive live` refuses without a baked site id and a running Matomo container. |

<Warning>
  `pnpm vulpy env golive live` will refuse if Matomo is not up. Self-hosting is not a consent exemption; you still need consent to track visitors.
</Warning>

## Start Matomo locally

<CodeGroup>
  ```bash Start theme={null}
  pnpm db:matomo:up
  ```

  ```bash Stop theme={null}
  pnpm db:matomo:down
  ```
</CodeGroup>

Local Matomo lives at `http://localhost:8081` by default. On a VPS with a domain, it is served at `https://analytics.<domain>`; on Tailscale-only installs, at `https://<magicdns>:8081`.

<Note>
  On NTFS or exFAT hosts, Matomo application files and its MariaDB fall back to `~/.local/share/<project>/matomo` and `~/.local/share/<project>/matomo-db` instead of `.data/`.
</Note>

## Production setup and verification

The production install runs Matomo setup automatically, but you can run the two operational scripts on demand:

<CodeGroup>
  ```bash Set up theme={null}
  pnpm deploy:matomo:setup
  ```

  ```bash Verify theme={null}
  pnpm deploy:matomo:verify
  ```
</CodeGroup>

`deploy:matomo:verify` checks the privacy and legal gates that gate `env golive live`.

## Two analytics lanes

Vulpy Commerce separates behavioral analytics from operational reporting. Each has different consent requirements and a different destination.

| Lane                  | Consent                   | Destination                           | Covers                                                                      |
| --------------------- | ------------------------- | ------------------------------------- | --------------------------------------------------------------------------- |
| Matomo (behavioral)   | Analytics opt-in required | Browser after consent                 | Pageviews, search, product / cart / checkout funnel, pseudonymized purchase |
| Operational reporting | No browser consent        | Medusa `commerceReporting` aggregates | Orders placed, paid, cancelled, refunded, fulfilled; units; revenue buckets |

<Note>
  Purchase events send Matomo a pseudonymized order id. If you have also configured GTM/GA4 via `NEXT_PUBLIC_GTM_ID`, GTM gets the merchant `display_id`. Logged-in `user_id` is a hashed customer id only.
</Note>

## Consent, privacy, and PII

* No Matomo script, request, or `_pk_*` cookie is loaded before the visitor opts in on the storefront.
* Withdrawing consent clears cookies and stops requests.
* GPC (Global Privacy Control) is treated as denial.
* Payloads never contain email, name, address, raw customer or order IDs, JWTs, card data, or unrestricted query strings.
* Purchases are only reported on the order confirmation page, deduped, so payment-return polling does not double-count.

## Add events for a new feature

When you build storefront UX that affects funnel or engagement (forms, CTAs, filters, drawers, auth outcomes, promotions, new checkout steps), instrument Matomo in the same change. Reuse the helpers in `apps/storefront/src/lib/analytics/`:

* `trackCustomEvent(category, action, name?, value?)` for custom events
* `trackProductImpression` and `trackSelectItem` for catalog interactions
* Cart mutations flow through `applyCartResult` on `CartContext`

Gate every event with `useHasAnalyticsConsent()`, or rely on `pushMatomoCommand`, which no-ops without consent and configuration.

<CardGroup cols={2}>
  <Card title="Go live" icon="rocket" href="/deploy/going-live">
    The go-live checklist, including Matomo gates.
  </Card>

  <Card title="Manage orders" icon="receipt" href="/shop/orders">
    Operational reporting is separate from Matomo.
  </Card>
</CardGroup>
