# Introduction (https://talivia.com/docs)



Talivia is revenue-first analytics for founders and small teams. It tracks visits, sessions, sources, events, product journeys, search keywords, and payments in one workspace so you can see what actually creates revenue.

Talivia is analytics with payment attribution, session-level revenue, native Stripe, Yolfi, and Dodo Payments connections, a Manual Payment API, search integrations, and practical collaboration for sharing a website with another user.

## What Talivia tracks [#what-talivia-tracks]

* Visits, sessions, pages, referrers, campaigns, countries, devices, browsers, and operating systems.
* Custom events from data attributes or `window.talivia.track`.
* Session replay and Web Vitals when enabled for a website.
* Revenue from connected payment providers, checkout return URLs, and the Manual Payment API.
* Search queries from Google Search Console and Bing Webmaster with estimated revenue allocation.

## Recommended path [#recommended-path]

1. Add your website.
2. Install the tracking script.
3. Confirm that visits appear in the dashboard.
4. Connect revenue sources when checkout is ready.
5. Invite teammates or viewers if someone else needs access.




## Use these docs [#use-these-docs]

Start with **Installation** if you only need the script. Use **Tracking** for JavaScript and data-attribute examples. Use **Revenue** and **Attribution** when payments need to connect back to sessions and traffic sources.


---

# AI agents and MCP (https://talivia.com/docs/ai-agents)



Talivia exposes an account-level [Model Context Protocol](https://modelcontextprotocol.io/) endpoint at:

```text
https://talivia.com/mcp
```

Connect it once to let an approved AI agent work across the websites your Talivia account can access. The agent can read the same period-based analytics available in Talivia–including events, goals, funnels, acquisition, revenue, payments, journeys, and data quality–and can also install and verify tracking or open secure payment-provider setup.

## Choose your client [#choose-your-client]




Codex

Connect from the CLI with remote MCP and OAuth.




ChatGPT

Create a custom app in Apps & Connectors.




Claude

Add Talivia as a custom web connector.




Other MCP clients

Use Streamable HTTP and OAuth discovery.

## How authorization works [#how-authorization-works]

1. Add `https://talivia.com/mcp` to your MCP client.
2. The first protected request returns an OAuth challenge with Talivia's authorization metadata.
3. Your client opens Talivia in the browser. Sign in if necessary.
4. Review the requested scopes and approve the connection.
5. The client stores a scoped access token that remains active until you revoke the connection.

The agent never receives your Talivia password. Payment provider secrets also stay in Talivia: when Stripe or another provider needs authorization, the MCP tool returns a secure browser handoff instead of asking the agent to handle credentials.

You can review or revoke approved connections at any time in **Settings → AI agents**. Revocation immediately disables the stored token.

## Local npm bridge [#local-npm-bridge]

If your client expects a local stdio MCP server, use the published Talivia package:

```bash
npx -y @talivia/agent setup --agent codex
npx -y @talivia/agent checkin --agent codex
codex mcp add talivia -- npx -y @talivia/agent mcp
```

The setup command opens Talivia for browser approval. Check-in stores the approved, revocable local credential in `~/.talivia/config.json`, and the final command lets Codex start the authenticated stdio bridge.

## Codex [#codex]

Add the hosted endpoint:

```bash
codex mcp add talivia --url https://talivia.com/mcp
```

Then start browser authorization:

```bash
codex mcp login talivia
```

After approval, ask Codex:

```text
Set up Talivia for this project. Select or create the correct website, install the tracker,
connect revenue through a secure browser handoff, and verify that real data is arriving.
```

## ChatGPT [#chatgpt]

1. Open **ChatGPT → Settings → Apps & Connectors**.
2. Create a custom app named `Talivia`.
3. Set the MCP server URL to `https://talivia.com/mcp` and choose OAuth.
4. Save the app, then complete Talivia sign-in and consent in the browser.
5. Enable Talivia in a chat before asking it to review or finish setup.

## Claude [#claude]

1. Open **Claude → Customize → Connectors → Add custom connector**.
2. Name the connector `Talivia` and use `https://talivia.com/mcp` as the remote MCP URL.
3. Complete Talivia sign-in and consent in the browser.
4. In a conversation, open the `+` menu, choose **Connectors**, and enable Talivia.

## Claude Code [#claude-code]

Register the hosted endpoint:

```bash
claude mcp add --transport http talivia https://talivia.com/mcp
```

The first protected tool call starts browser authorization.

## Other MCP clients [#other-mcp-clients]

Use a Streamable HTTP server with OAuth discovery:

```json
{
  "talivia": {
    "type": "http",
    "url": "https://talivia.com/mcp",
    "auth": "oauth"
  }
}
```

Your client must support MCP OAuth authorization-server discovery and the browser authorization flow. If it does not, use one of the supported clients above.

## What the agent can do [#what-the-agent-can-do]

Talivia exposes focused tools for setup and analysis:

* Read a period overview with traffic, conversions, revenue, refunds, and a previous-period comparison.
* Inspect event names, event properties, action counts, unique visitors, and time series.
* Read saved goal definitions and calculate their results for the selected period.
* Read saved funnel definitions and calculate step reach and drop-off.
* Read every Talivia dimension shown in the dashboard, including channel, referrer, every UTM field, landing and exit pages, hostname, geography, browser, device, language, and visitor ID. Revenue-capable dimensions also include payments and attributed revenue.
* Read the Keywords view, which combines tracked UTM terms with connected Google Search Console and Bing Webmaster queries, clicks, impressions, CTR, position, pages, and estimated organic revenue.
* Read confirmed payments, new customers, renewals, refunds, disputes, subscriptions, and revenue attribution.
* Inspect aggregate visitor journeys or trace a specific payment from acquisition through product activity and attribution.
* Diagnose freshness, identity coverage, provider sync failures, pending checkout returns, and unattributed payments.
* Create or select a website, install the tracker, connect a payment provider through a secure handoff, and verify ingestion.

Every analytics response states the effective period, timezone, generation time, and whether the result is ready or empty. `startDate` and `endDate` accept any valid range, so an agent can request 30 days, 40 days, or exact campaign dates instead of relying on fixed presets. Empty data and a failed query are reported differently.

Talivia reports observed product and payment data, including its existing Keywords view. Google Ads account spend, ad creative, bidding keywords, and ad search terms still come from the advertising platform and should be joined with Talivia results by the agent.

For example:

```text
Analyze the last 30 days for my website. Use Talivia for product events, goals, funnels,
traffic sources, confirmed payments, customer journeys, and data quality. Combine those
results with Google Ads spend before calculating CAC or ROAS.
```

## Troubleshooting [#troubleshooting]

### The browser does not open [#the-browser-does-not-open]

Confirm that the client supports OAuth for remote MCP servers. Remove the existing Talivia entry, add it again, and retry authorization.

### The endpoint is unavailable [#the-endpoint-is-unavailable]

Open **Settings → AI agents** and check the endpoint status. A healthy endpoint shows **Ready to connect**.

### The wrong account was authorized [#the-wrong-account-was-authorized]

Revoke the connection in **Settings → AI agents**, sign in to the intended Talivia account in your browser, and connect again.

### The agent cannot see a website [#the-agent-cannot-see-a-website]

The MCP connection follows the same account and website permissions as the Talivia UI. Confirm that the signed-in account has access to that website.


---

# Cross-domain tracking (https://talivia.com/docs/cross-domain-tracking)



Browser cookies cannot be shared between unrelated root domains. Talivia uses a short-lived signed linker instead.

1. Open **Settings -> Attribution**.
2. Add every owned root domain used by the journey.
3. Keep **Cross-domain tracking** enabled.
4. Copy the refreshed snippet from **Settings -> Tracking** to each domain.

The generated snippet includes `data-cross-domain-domains`. After the first tracking response, Talivia decorates matching links with `_tlv`. The destination verifies the signature, continues the anonymous visitor/session, and removes `_tlv` from the address before storing the page view.

The linker expires after five minutes and is scoped to one Talivia website ID. A modified token, expired token, or token issued for another website is rejected.

Subdomains do not need the linker. Use [Subdomain tracking](https://talivia.com/docs/subdomain-tracking) for `example.com` and `app.example.com`.


---

# Distinct IDs (https://talivia.com/docs/distinct-ids)



Talivia is anonymous by default. The tracker creates a visitor key and session key in browser storage, then records page views without requiring a user id.

Use `identify` when your app knows who the visitor is.

```js
window.talivia.identify('user_123', {
  email: 'founder@example.com',
  name: 'Founder',
});
```

## Payment customer fields [#payment-customer-fields]

Talivia recognizes common payment/customer fields:

```js
window.talivia.identify('user_123', {
  stripeCustomerId: 'cus_123',
  providerName: 'stripe',
  providerCustomerId: 'cus_123',
  externalCustomerId: 'user_123',
  emailHash: 'sha256-email-hash',
});
```

These fields help connect Stripe or manual payments back to the visitor, especially when checkout happens later.

## What identify does [#what-identify-does]

Identify sends an `identify` collection event, stores session data, and links the current visitor/session to the customer identity.

## When to call it [#when-to-call-it]

Call identify after login, signup, account creation, or whenever a new payment customer is created.


---

# Conversion funnels (https://talivia.com/docs/funnels)



Conversion funnels show how many visitors complete a sequence of important actions, where they
leave, and which transition needs attention. A funnel is saved for a website, so you can return to
the same journey while changing the dashboard date range.




## Create a funnel [#create-a-funnel]

1. Open a website and select **Funnels** in the lower analytics panel.
2. Select the &#x2A;*+** button. When the website has no funnels yet, you can also select **Add funnel**
   in the middle of the panel.
3. Give the funnel a name that describes the outcome, such as `Activation path` or
   `Pricing to payment`.
4. Add between 2 and 8 steps in the order visitors should complete them.
5. For every step, select **Viewed page** or **Triggered event**, then choose its page path or event
   name.
6. For a custom event with event data, add property filters when you need to measure a more
   specific action.
7. Select **Save**.




Need an event that is not available in the step selector yet? [Track the action as a custom
event](https://talivia.com/docs/track-events), perform it once on the tracked website, then return to the funnel
editor.

## Filter an event step [#filter-an-event-step]

Filters are available after a step uses **Triggered event** and the selected event has event data.
Select **Filter**, then choose a property, an operator, and a value. Multiple filters on the same
step must all match the same event occurrence.

Visibility events created with `data-talivia-visible` expose three useful properties:

| Property                | What to enter in a funnel filter                                                                                           |
| ----------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `visibility_percentage` | A whole percentage such as `70` or `80`. This is how much of the element was actually visible when Talivia sent the event. |
| `threshold`             | A ratio such as `0.5` or `0.7`. This is the configured visibility threshold.                                               |
| `delay`                 | A duration in milliseconds such as `0` or `700`. This is how long the element had to remain continuously visible.          |

For example, to use only pricing-section events configured with an 80% visibility requirement,
select that visibility event and add the filter `threshold is 0.8`. Use
`visibility_percentage is 80` when you need the actual recorded percentage to equal 80. See [Track
when an element becomes visible](https://talivia.com/docs/track-events#track-when-an-element-becomes-visible) for the
HTML attributes, defaults, value ranges, and complete event payload.

## How visitors are counted [#how-visitors-are-counted]

Talivia counts unique visitors, not the total number of events. A visitor reaches a step when the
same visitor completes that step after the previous one.

* Steps must happen in the configured order, but they do not need to be consecutive. Other page
  views or events can happen between them.
* A visitor can enter the funnel whenever they match the first step during the selected reporting
  period.
* The selected dashboard date range is also the automatic completion window. There is no separate
  window to configure.
* Changing the date range recalculates the funnel without changing its saved steps.

For `/` → `scroll_to_pricing` → `/pricing`, a visitor is counted at step 3 only after the same
visitor first viewed `/`, then triggered `scroll_to_pricing`, and then viewed `/pricing` within
the selected reporting period.

## Read the funnel [#read-the-funnel]

* **Visitor count:** The number of unique visitors who reached that step.
* **Ribbon width:** A visual comparison of visitor volume across the steps.
* **Drop-off:** The percentage lost between two adjacent steps. For example, if 34 visitors reach
  one step and 25 reach the next, the drop-off is `(34 - 25) / 34 = 26.5%`.
* **Conversion rate:** The percentage of first-step visitors who reached the final step:
  `final step / first step`.

Hover over a ribbon segment to inspect its transition. The tooltip shows the previous step, the
number of visitors who dropped off, the current step, the percentage that continued from the
previous step, and the percentage that reached it from the start. The first step has no drop-off
because there is no earlier step to compare.

Use the list on the right to switch between saved funnels. Use the &#x2A;*•••** menu next to the overall
conversion rate to edit or delete the selected funnel. When a funnel has more steps than fit in the
panel, scroll horizontally to inspect the rest.

Funnels shown inside the Overview analytics panel are included automatically in read-only public
links that share Overview. There is no separate Funnels switch to enable for that panel. Public
viewers can inspect saved funnel results but cannot add, edit, or delete funnels.

## Design a useful funnel [#design-a-useful-funnel]

A useful funnel answers one clear question: where do people stop before reaching a meaningful
outcome? Define the outcome first, then work backward to the earliest step that represents the
right audience.

* **Choose a meaningful start.** This could be a landing page, the first product view, a signup, or
  the beginning of a specific workflow. Avoid a start so broad that unrelated visitors distort the
  result.
* **Make the final step the outcome.** Use a completed signup, activated account, submitted lead,
  successful payment, or another action that represents real progress.
* **Keep only diagnostic steps.** An intermediate step should help explain why visitors did or did
  not reach the outcome. You do not need to include every page or click.
* **Use pages and events intentionally.** Page steps are useful when reaching a destination matters.
  Event steps are better for actions such as submitting a form, opening checkout, using a feature,
  or completing a task.
* **Use stable names.** Choose paths and event names that will remain valid when interface text or
  visual design changes.
* **Separate different journeys.** Acquisition, activation, purchasing, and retention usually
  answer different questions and are easier to understand as separate funnels.
* **Start short.** Two to five steps are usually enough for the first version. Add more only when
  they make a large drop-off easier to diagnose. A funnel can contain up to eight steps.

After changing a page or workflow, keep the funnel definition unchanged and compare equivalent date
ranges. This makes it easier to see whether the change improved the transition you targeted instead
of merely changing who entered the funnel.


---

# Goals (https://talivia.com/docs/goals)



Goals let you define important outcomes and watch conversion rates over time.

## Goal examples [#goal-examples]

* A visit to `/pricing`.
* A custom event such as `signup-click`.
* A checkout return page.
* A session property or event-data match.

## How to use goals [#how-to-use-goals]

Create goals from the website reports area. Choose the condition that represents success, then review conversion count and rate across the selected date range.

## Revenue goals [#revenue-goals]

For paid conversion analysis, prefer the Revenue and Attribution reports. Goals are best for product milestones that may happen before payment.


---

# Installation (https://talivia.com/docs/install)



Installation has two useful steps: add the tracker to your site, then connect the payment system that creates revenue.

## Step 1. Install the tracker [#step-1-install-the-tracker]

The Talivia tracker works anywhere you can add a script tag. Start with the universal snippet, then use a framework guide only when you need exact placement for your stack.

### Universal snippet [#universal-snippet]

In the app, open the website, go to **Settings -> Tracking**, and copy the snippet generated for that website.

```html
<script
  defer
  src="https://talivia.com/script.js"
  data-website-id="YOUR_WEBSITE_ID"
  data-domain="example.com"
></script>
```

Always copy the snippet from your website settings. Replace YOUR\_WEBSITE\_ID with the real ID from Talivia Settings -> Tracking. Do not reuse the example value.

Place the snippet before the closing `</body>` tag, or load it through your framework's shared document/layout component.

### Install with a coding agent [#install-with-a-coding-agent]

**Settings → Tracking** also provides a short, ready-to-copy prompt with your website's actual script, domain, and installation guide link. Give it to a coding agent working in your site's codebase. The prompt asks the agent to install the tracker across the site using the framework's shared layout and send a `signup` event after registration succeeds. Review the resulting code and verify a real page view and signup event in Talivia.

If you are preparing the request manually, use this version and replace the placeholder with the complete snippet from your website settings:

```text
Install Talivia in this project. Add the script below site-wide via the shared layout. After a successful signup, call window.talivia?.track('signup'). Verify events arrive.

PASTE_TRACKING_SCRIPT_HERE
```

Talivia Cloud usually includes `data-domain` in the generated snippet. A website running on one hostname also works without it, but keeping the generated value lets the root website and its subdomains share the same visitor and 30-minute rolling session. You do not need to add or remove this attribute manually for a normal installation.

If your flow crosses to a different root domain, add the owned domains under **Settings -> Attribution** and copy the refreshed snippet.

Tracking overview

See what the script records automatically and which runtime functions it exposes.

Tracker configuration

Understand optional script attributes, storage, filtering, and collection settings.

Subdomain tracking

Keep one visitor identity across a root website, app, docs, and checkout.

### Framework and builder guides [#framework-and-builder-guides]

If your site uses a framework, CMS, ecommerce platform, or no-code builder, open the guide below for the exact place to paste the same snippet. Framework examples focus on placement and may omit optional attributes, so use the complete code generated in **Settings -> Tracking**.

Next.js

App Router and shared layouts.

React

Vite, CRA, and static HTML shells.

Vue

Vue apps and shared HTML entry points.

Nuxt

Nuxt app head and plugin setup.

Angular

Workspace index.html or runtime injection.

SvelteKit

Global app template placement.

Astro

Base layouts and content sites.

Remix

Root document and Scripts component.

SolidStart

Root document setup.

Qwik

Root layout and head placement.

Gatsby

SSR document hooks.

Expo

Expo Web and static HTML.

Laravel

Blade layouts and shared app views.

Django

Base templates and inherited pages.

Ruby on Rails

Application layout and ERB templates.

Express

EJS, Pug, or static HTML shells.

NestJS

Server-rendered templates or static clients.

Flask

Jinja base templates.

Phoenix

Root layouts and LiveView pages.

WordPress

Theme footer, child themes, or snippet plugins.

Shopify

Theme layout and storefront pages.

Wix

Dashboard custom code settings.

Webflow

Site custom code and project settings.

Squarespace

Code injection for all pages.

Framer

Custom code before body end.

Tilda

Site-wide HTML before body close.

## Step 2. Connect payments [#step-2-connect-payments]

Traffic only becomes useful revenue analytics after Talivia can see payment events. Choose the payment path that matches your checkout.

Stripe

Connect a restricted API key and let Talivia configure webhooks.




Yolfi

Connect the account and configure the Checkout Session return URL.

LemonSqueezy

Use provider events when LemonSqueezy powers checkout.




Polar

Use Polar payment events when your product sells through Polar.




Dodo Payments

Connect one API key; Talivia creates the payment and refund webhook.




Manual Payment API

Send payments from your backend or custom processor.

For hosted providers that expose a unique checkout return ID, configure that provider's return
placeholder. For custom payment flows, pass `window.talivia.getSessionId()` as supported provider
metadata or as `sessionId` to the Manual Payment API. The Revenue guides document each provider's
preferred signal.

## Verify the install [#verify-the-install]

1. Open your website in a normal browser tab.
2. Visit a page that includes the tracker.
3. Return to Talivia and open the website dashboard.
4. Look for a new session, page view, referrer, browser, and country.
5. After payment setup, make a test payment and confirm revenue appears in the same website.


---

# Angular (https://talivia.com/docs/installation-guides/angular)



For Angular apps, add the tracker to the HTML shell that wraps the app.




## Add the script [#add-the-script]

Open `src/index.html` and place the snippet before the closing `</body>` tag.

```html
<app-root></app-root>
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
</body>
```

Replace the website ID. Use the ID from Talivia Settings -> Tracking for this exact Angular domain.

Build or run the app, open a page, and check Talivia for the first session.


---

# Astro (https://talivia.com/docs/installation-guides/astro)



Add Talivia to the shared layout used by your Astro pages.




## Add the script [#add-the-script]

Open your base layout, for example `src/layouts/BaseLayout.astro`, and place the snippet before the closing `</body>` tag.

```astro
---
const { title } = Astro.props;
---

<html lang="en">
  <head>
    <title>{title}</title>
  </head>
  <body>
    <slot />
    <script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
  </body>
</html>
```

Replace the website ID. Use the ID from Talivia Settings -> Tracking for this Astro site.

Deploy or run the site, visit a page, and confirm the new session in Talivia.


---

# Django (https://talivia.com/docs/installation-guides/django)



Install Talivia in the base template inherited by your public pages.




## Base template [#base-template]

Open a shared template such as `templates/base.html` and place the snippet before `</body>`.

```html
    <script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
</body>
</html>
```

If different parts of the site use different base templates, add Talivia to each public base template.

Do not leave the placeholder. Replace YOUR\_WEBSITE\_ID with the value from Talivia Settings -> Tracking.

Deploy the template, visit a page, and confirm the first session in Talivia.


---

# Expo (https://talivia.com/docs/installation-guides/expo)



Talivia's browser tracker is for web pages. Use this guide for Expo Web or web builds of an Expo Router app.




## Expo Router [#expo-router]

Create or update `app/+html.tsx` and place the script in the body.

```tsx
import { ScrollViewStyleReset } from 'expo-router/html';

export default function Root({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <head>
        <ScrollViewStyleReset />
      </head>
      <body>
        {children}
        <script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID" />
      </body>
    </html>
  );
}
```

## Expo web HTML [#expo-web-html]

If your project exposes a web HTML template, add the universal snippet before `</body>`.

```html
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
```

Native apps are different. This script tracks browser traffic only. For iOS or Android screens in an Expo app, use the [React Native SDK](https://talivia.com/docs/mobile-analytics/react-native).


---

# Express (https://talivia.com/docs/installation-guides/express)



Use the shared HTML template that wraps your Express pages.




## Template apps [#template-apps]

If you use EJS, Pug, Handlebars, or another view engine, place the snippet in the base layout before `</body>`.

```html
<main>
  <!-- page content -->
</main>
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
</body>
```

## Static apps [#static-apps]

If Express serves a static frontend, add the snippet to the generated `index.html`.

Replace the website ID. Use the value from Talivia Settings -> Tracking.

Restart the server, open a page, and verify the session in Talivia.


---

# Flask (https://talivia.com/docs/installation-guides/flask)



Add Talivia to the base Jinja template used by your pages.




## Add the script [#add-the-script]

Open your base template, often `templates/base.html`, and place the snippet before `</body>`.

```html
{% block content %}{% endblock %}
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
</body>
```

Replace the website ID. Use the value from Talivia Settings -> Tracking.

Run Flask, open a page, and confirm Talivia receives a session.


---

# Framer (https://talivia.com/docs/installation-guides/framer)



Use Framer custom code to load Talivia across the published site.




## Add custom code [#add-custom-code]

1. Open the Framer project.
2. Go to Site Settings.
3. Open the Custom Code area.
4. Add the Talivia snippet before the closing body tag.
5. Publish the site.

```html
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
```

Replace the website ID. Copy the ID from Talivia Settings -> Tracking for this Framer site.

Visit the published site and verify the first Talivia session.


---

# Gatsby (https://talivia.com/docs/installation-guides/gatsby)



Use Gatsby's SSR hooks so Talivia appears on every generated page.




## Add the script [#add-the-script]

Create or open `gatsby-ssr.js` and append the Talivia script to the post-body components.

```jsx
import React from 'react';

export const onRenderBody = ({ setPostBodyComponents }) => {
  setPostBodyComponents([
    <script
      key="talivia"
      defer
      src="https://talivia.com/script.js"
      data-website-id="YOUR_WEBSITE_ID"
    />,
  ]);
};
```

Replace the website ID. Use the ID from Talivia Settings -> Tracking.

Build or run Gatsby, open a page, and verify the session in Talivia.


---

# Laravel (https://talivia.com/docs/installation-guides/laravel)



Add Talivia to the Blade layout that wraps every public page.




## Blade layout [#blade-layout]

Open a shared layout such as `resources/views/layouts/app.blade.php` and place the snippet before `</body>`.

```html
    <script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
</body>
</html>
```

If your marketing site uses another layout, add the snippet there instead.

Use the website ID from Talivia. Each Laravel app or domain should use the ID generated for that website.

## Verify [#verify]

Visit the Laravel site in a browser, then open Talivia and check the website dashboard for a new session.


---

# NestJS (https://talivia.com/docs/installation-guides/nest-js)



NestJS can serve templates or a separate frontend. Add Talivia wherever the browser HTML shell is created.




## Server-rendered templates [#server-rendered-templates]

Place the snippet in the shared layout or template before the closing `</body>` tag.

```html
<main>
  <!-- page content -->
</main>
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
</body>
```

## API-only apps [#api-only-apps]

If NestJS only serves an API, install Talivia in the frontend app instead, such as Next.js, React, Angular, or Vue.

Replace the website ID. Copy it from Talivia Settings -> Tracking for the public website.

Open the public app and verify the first session in Talivia.


---

# Next.js (https://talivia.com/docs/installation-guides/next-js)



Use the root layout so the tracker loads on every route.




## App Router [#app-router]

Open `app/layout.tsx` and add `next/script`.

```tsx
import Script from 'next/script';

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          src="https://talivia.com/script.js"
          data-website-id="YOUR_WEBSITE_ID"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}
```

Replace the website ID. Use the ID from Talivia Settings -> Tracking for this exact website.

## Pages Router [#pages-router]

If your app uses `pages/_document.tsx`, place the script before `</body>`.

```tsx
import { Html, Head, Main, NextScript } from 'next/document';

export default function Document() {
  return (
    <Html>
      <Head />
      <body>
        <Main />
        <script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID" />
        <NextScript />
      </body>
    </Html>
  );
}
```

## Verify [#verify]

Run the app, open a page, then return to Talivia and check for a new session.


---

# Nuxt (https://talivia.com/docs/installation-guides/nuxt)



Use Nuxt's global app head so the tracker loads on every route.




## Add the script [#add-the-script]

Open `nuxt.config.ts` and add the Talivia script to `app.head.script`.

```ts
export default defineNuxtConfig({
  app: {
    head: {
      script: [
        {
          src: 'https://talivia.com/script.js',
          defer: true,
          'data-website-id': 'YOUR_WEBSITE_ID',
        },
      ],
    },
  },
});
```

Replace the website ID. Copy it from Talivia Settings -> Tracking for this Nuxt website.

Run the app, open a public route, and verify the new session in Talivia.


---

# Phoenix (https://talivia.com/docs/installation-guides/phoenix)



Add Talivia to the shared root layout so the tracker loads across Phoenix pages.




## Add the script [#add-the-script]

Open the root layout, often `lib/my_app_web/components/layouts/root.html.heex`, and place the snippet before `</body>`.

```html
<%= @inner_content %>
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
</body>
```

Replace the website ID. Copy it from Talivia Settings -> Tracking.

Open the Phoenix site and check Talivia for the new visit.


---

# Qwik (https://talivia.com/docs/installation-guides/qwik)



Use the root layout so the tracker is included on every public page.




## Add the script [#add-the-script]

Open the root layout or document file and add the Talivia snippet near the end of the body.

```tsx
export default component$(() => {
  return (
    <>
      <Slot />
      <script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID" />
    </>
  );
});
```

Replace the website ID. Copy it from Talivia Settings -> Tracking for the Qwik site.

Open a route and confirm the visit in Talivia.


---

# React (https://talivia.com/docs/installation-guides/react)



For React apps, add the tracker to the HTML shell that wraps the app.




## Vite [#vite]

Open `index.html` and place the snippet before the closing `</body>` tag.

```html
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
```

## Create React App [#create-react-app]

Open `public/index.html` and place the snippet before the closing `</body>` tag.

```html
<div id="root"></div>
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
```

Use your Talivia website ID. The example ID is only a placeholder.

Talivia listens to browser history changes, so route changes in React Router are tracked after the script loads.


---

# Remix (https://talivia.com/docs/installation-guides/remix)



Use the root document so the tracker is included on every route.




## Add the script [#add-the-script]

Open `app/root.tsx` and place the snippet before Remix's `Scripts` component.

```tsx
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react';

export default function App() {
  return (
    <html lang="en">
      <head>
        <Meta />
        <Links />
      </head>
      <body>
        <Outlet />
        <ScrollRestoration />
        <script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID" />
        <Scripts />
      </body>
    </html>
  );
}
```

Replace the website ID. Copy it from Talivia Settings -> Tracking.

Open a route and verify that Talivia receives a session.


---

# Ruby on Rails (https://talivia.com/docs/installation-guides/ruby-on-rails)



Add Talivia to the application layout so every rendered page includes the tracker.




## Add the script [#add-the-script]

Open `app/views/layouts/application.html.erb` and place the snippet before the closing `</body>` tag.

```html
<%= yield %>
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
</body>
```

Replace the website ID. Copy the ID from Talivia Settings -> Tracking for this Rails domain.

Open the Rails app in a browser and check Talivia for the new session.


---

# Shopify (https://talivia.com/docs/installation-guides/shopify)



Install Talivia in the Shopify theme layout so storefront pages are tracked.




## Theme layout [#theme-layout]

Open the Shopify theme code editor and edit `layout/theme.liquid`. Place the snippet before the closing `</body>` tag.

```html
    <script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
</body>
</html>
```

Storefront first. This tracks the online store pages where the theme is rendered. Checkout pages may be controlled separately depending on your Shopify plan and setup.

## Verify [#verify]

Preview or publish the theme, visit a product or landing page, and confirm the visit appears in Talivia.


---

# SolidStart (https://talivia.com/docs/installation-guides/solid-start)



Add Talivia to the root document so it loads across the app.




## Add the script [#add-the-script]

Open the root entry file where `StartServer`, `Scripts`, or the document body is defined, then place the snippet before closing the body.

```tsx
import { Scripts } from '@solidjs/start';

export default function Root() {
  return (
    <html lang="en">
      <body>
        <script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID" />
        <Scripts />
      </body>
    </html>
  );
}
```

Replace the website ID. Use the value from Talivia Settings -> Tracking.

Run the app and open a page to verify the first session.


---

# Squarespace (https://talivia.com/docs/installation-guides/squarespace)



Use Squarespace code injection so Talivia loads on every public page.




## Add code injection [#add-code-injection]

1. Open the Squarespace site dashboard.
2. Go to Settings and open Code Injection.
3. Paste the Talivia snippet in the footer or body-end injection area.
4. Save and publish.

```html
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
```

Replace the website ID. Use the ID from Talivia Settings -> Tracking.

Open the published Squarespace site and check Talivia for a new session.


---

# SvelteKit (https://talivia.com/docs/installation-guides/svelte-kit)



Use the app template so Talivia loads once for the whole SvelteKit site.




## Add the script [#add-the-script]

Open `src/app.html` and place the snippet before the closing `</body>` tag.

```html
<body data-sveltekit-preload-data="hover">
  <div style="display: contents">%sveltekit.body%</div>
  <script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
</body>
```

Replace the website ID. Copy the ID from Talivia Settings -> Tracking.

Talivia tracks normal page views and client-side route changes after the script loads.


---

# Tilda (https://talivia.com/docs/installation-guides/tilda)



Add Talivia as site-wide HTML so every published page is tracked.




## Site-wide code [#site-wide-code]

1. Open the Tilda project settings.
2. Find the custom code or HTML injection section.
3. Paste the Talivia script before the closing body tag.
4. Publish the project again.

```html
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
```

Use the correct website ID. If you have multiple Tilda domains or projects, each one should use its own Talivia website ID.

After publishing, open the live site and check Talivia for a page view.


---

# Vue (https://talivia.com/docs/installation-guides/vue)



Add the Talivia script to the HTML file that loads your Vue app.




## Vue with Vite [#vue-with-vite]

Open `index.html` and place the snippet near the end of `body`.

```html
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
```

## Nuxt-style projects [#nuxt-style-projects]

If your Vue project has a global app template or head/script configuration, add the same tracker once globally. Avoid adding it inside individual pages.

```html
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
```

Replace YOUR\_WEBSITE\_ID. Copy the real value from Talivia Settings -> Tracking.

After deploying, open any public page and check the Talivia dashboard for a new visit.


---

# Webflow (https://talivia.com/docs/installation-guides/webflow)



Use Webflow custom code to include Talivia on every published page.




## Add custom code [#add-custom-code]

1. Open the Webflow project.
2. Go to Project Settings.
3. Open the Custom Code section.
4. Paste the Talivia snippet before the closing body tag.
5. Save changes and publish the site.

```html
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
```

Replace the website ID. Copy it from Talivia Settings -> Tracking for the Webflow domain.

Visit the published site and verify the new session in Talivia.


---

# Wix (https://talivia.com/docs/installation-guides/wix)



Use Wix custom code to load Talivia on every public page.




## Add custom code [#add-custom-code]

1. Open your Wix dashboard.
2. Go to the site's custom code or tracking tools area.
3. Add a new custom code snippet.
4. Paste the Talivia script.
5. Set it to load on all pages, near the end of the body.

```html
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
```

Replace the website ID. Copy it from Talivia Settings -> Tracking for the Wix domain you are measuring.

Publish the Wix site, open it in a browser, and verify the new visit in Talivia.


---

# WordPress (https://talivia.com/docs/installation-guides/wordpress)



The safest WordPress setup is to add Talivia once site-wide through a child theme or a trusted custom-code plugin.




## Option 1: Child theme [#option-1-child-theme]

Add the script through the `wp_footer` hook in your child theme's `functions.php`.

```php
add_action('wp_footer', function () {
    ?>
    <script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
    <?php
});
```

## Option 2: Custom-code plugin [#option-2-custom-code-plugin]

Use a plugin that inserts code before the closing `</body>` tag and paste the universal snippet.

```html
<script defer src="https://talivia.com/script.js" data-website-id="YOUR_WEBSITE_ID"></script>
```

Keep it site-wide. Add the tracker once globally, not inside individual posts.

Open the WordPress site in a normal browser tab and check Talivia for a new session.


---

# Integrations (https://talivia.com/docs/integrations)



Integrations add context that the browser tracker cannot collect by itself. Connect a platform to see its activity alongside visitors, revenue, and other website metrics.




X mention monitoring

See conversations about your product or website alongside traffic and revenue.




GitHub commits

See your latest commits on the analytics chart and find what moves the needle.


---

# AI bot traffic tracking (https://talivia.com/docs/integrations/bot-traffic)



# AI bot traffic tracking [#ai-bot-traffic-tracking]

Bot traffic is a **Talivia Cloud** server-side feature. It records recognized crawler requests in a dedicated data set, separate from human pageviews, visitors, conversions, and revenue.

A recorded request shows that a matching crawler requested a URL. It does not prove citation, recommendation, use in an answer, cryptographic identity, or revenue impact.

## 1. Create a website token [#1-create-a-website-token]

Open **Website settings → Bot traffic**, enable collection, and generate a token. Each token belongs to one website. Copy it immediately because it is displayed only once, and store it as a server-side secret. Rotating it revokes the previous token.

```bash
pnpm add @talivia/bot-traffic
```

```bash
TALIVIA_BOT_TOKEN=<one-time-token>
```

## Next.js middleware or proxy [#nextjs-middleware-or-proxy]

Next middleware runs before the final page response. Use request-only tracking: `NextResponse.next()` is not the final page status and must not be reported as one.

```ts
import { NextResponse } from 'next/server';
import { getHeader, trackBotRequestInBackground } from '@talivia/bot-traffic/next';

export function middleware(request, event) {
  trackBotRequestInBackground(
    request,
    {
      token: process.env.TALIVIA_BOT_TOKEN!,
      // Only if your proxy overwrites this header for every request:
      getSourceIp: value => getHeader(value.headers, 'x-real-ip'),
    },
    event,
  );
  return NextResponse.next();
}

export const config = { matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'] };
```

## Express [#express]

The Express adapter calls `next()` immediately and reports the final response status after the `finish` event.

```ts
import express from 'express';
import { createExpressBotMiddleware } from '@talivia/bot-traffic/express';

const app = express();
app.use(createExpressBotMiddleware({
  token: process.env.TALIVIA_BOT_TOKEN!,
}));
```

## Cloudflare Workers and Pages [#cloudflare-workers-and-pages]

```ts
import { withBotTracking } from '@talivia/bot-traffic/cloudflare';

export default {
  fetch: withBotTracking(
    (request, env) => env.ASSETS.fetch(request),
    { token: '<server-token>' },
  ),
};
```

For Pages Functions, process `context.request`, then call `trackBotRequestInBackground` with the final status and pass `context` as the third argument so `waitUntil` keeps delivery alive.

## Any JavaScript or TypeScript framework [#any-javascript-or-typescript-framework]

No named adapter is required when the framework exposes standard `Request` and `Response` objects:

```ts
import { trackBotRequestInBackground } from '@talivia/bot-traffic';

export async function handle(request, context) {
  const response = await yourFrameworkHandler(request);
  trackBotRequestInBackground(
    request,
    { token: process.env.TALIVIA_BOT_TOKEN!, status: response.status },
    context, // optional object with waitUntil(promise)
  );
  return response;
}
```

If only the incoming request is available, omit `status`. Request-only tracking still records which page the crawler attempted to fetch. Use `withBotTracking` only around a handler that returns the final `Response`. Use the awaited `trackBotRequest` function for tests or controlled background jobs, not on a latency-sensitive response path.

This generic pattern applies to Hono, Bun, Deno, custom Node.js Fetch servers, serverless functions, and other Fetch-compatible runtimes.

## Docker, Cloud Run, and reverse proxies [#docker-cloud-run-and-reverse-proxies]

If `request.url` contains an internal host such as `http://app:3000/docs`, set the real public origin:

```ts
{
  token: process.env.TALIVIA_BOT_TOKEN!,
  publicOrigin: 'https://example.com',
}
```

The package replaces only the origin and preserves the request path. `publicOrigin` must be an `http` or `https` origin without credentials, a path, query, or fragment. Talivia still validates the public hostname against the website that owns the token.

## Trusted crawler IP [#trusted-crawler-ip]

User-Agent strings can be spoofed. Talivia can compare the crawler address with provider-published CIDR ranges when a server integration supplies it through `getSourceIp`. The package never reads `X-Forwarded-For`, `X-Real-IP`, or another forwarding header automatically. Configure a resolver only when your reverse proxy removes every client-supplied copy and writes the direct client address itself.

The raw address is used transiently for verification and is never stored. Talivia stores only a keyed HMAC hash for repeat-request analysis. If a provider does not publish a suitable range, the event remains `unverified` rather than being presented as verified evidence.

## PHP, Go, Ruby, and other languages [#php-go-ruby-and-other-languages]

The JavaScript package is optional. Any server language can send this minimal event to the fixed endpoint:

```http
POST https://talivia.com/v1/bot-traffic
Authorization: Bearer <website-bot-token>
Content-Type: application/json

{
  "schemaVersion": 1,
  "hostname": "example.com",
  "path": "/docs/getting-started",
  "method": "GET",
  "userAgent": "GPTBot/1.0",
  "status": 200,
  "sourceIp": "203.0.113.10"
}
```

`status` and `sourceIp` are optional. Send `sourceIp` only when it came from the connection socket or a forwarding header that a trusted proxy always overwrites. Talivia Cloud derives provider, bot, category, and verification itself; do not send those fields.

### PHP example [#php-example]

Invoke this helper only after the application has sent the response. With PHP-FPM, call `fastcgi_finish_request()` first when available.

```php
function trackTaliviaBot(array $event, string $token): void {
    $ch = curl_init('https://talivia.com/v1/bot-traffic');
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => json_encode($event, JSON_UNESCAPED_SLASHES),
        CURLOPT_HTTPHEADER => [
            'Authorization: Bearer ' . $token,
            'Content-Type: application/json',
        ],
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT_MS => 1500,
    ]);
    curl_exec($ch);
    curl_close($ch);
}

// After your framework has produced and sent the final response:
if (function_exists('fastcgi_finish_request')) {
    fastcgi_finish_request();
}
trackTaliviaBot($event, getenv('TALIVIA_BOT_TOKEN'));
```

Call the helper only for likely crawler `GET` or `HEAD` document requests after the final status is known and the user response has been sent. Send a pathname without query strings or fragments. Do not send cookies, authorization headers, request bodies, visitor identifiers, referrers, or unrelated headers.

## Required custom-integration behavior [#required-custom-integration-behavior]

* Endpoint: `https://talivia.com/v1/bot-traffic`.
* Authentication: `Authorization: Bearer <website-bot-token>`.
* Content type: `application/json`.
* Required fields: `schemaVersion`, `hostname`, `path`, `method`, `userAgent`.
* Optional fields: `status` from `100` to `599`, and a trusted `sourceIp` (IPv4 or IPv6).
* Methods: document-like `GET` and `HEAD` requests.
* Keep payloads at or below 8 KiB and User-Agent at or below 512 characters.
* Strip query strings and fragments from `path`.
* Use a short timeout and fail open. A telemetry failure must never fail or delay the website response.
* Ignore framework internals such as Next.js RSC and prefetch requests so a page fetch is not counted several times.
* Do not trust User-Agent as proof of identity. Talivia performs central classification and network verification.

After deployment, use the detailed report to review request trends, providers, categories, pages, status codes, missing pages, and evidence-based verification confidence.


---

# Show GitHub commits (https://talivia.com/docs/integrations/github-commits)



Install the GitHub App to see your latest commits on your analytics chart and find what moves the needle. Commits appear as markers on the main analytics chart, so you can connect a change you shipped with the visitors and revenue that followed.

## Why show commits? [#why-show-commits]

Commits give useful context to your website analytics:

* See exactly what shipped before a traffic or revenue change.
* Compare release activity with conversion trends over time.
* Share a chart where the whole team can see cause and effect.

## How it works [#how-it-works]

You install the Talivia GitHub App on your account or organization and grant it read access to one repository. Talivia then imports the latest commits from the default branch and keeps them in sync automatically, checking for new commits every 20 minutes.

Hover over a commit marker on the chart to preview the commit messages. Select it to see the complete list for that moment and open any commit on GitHub.

The app only requests read access to repository contents. Talivia never stores your code – only the commit metadata shown on the chart: the message, author, and time.

## Connect a repository [#connect-a-repository]

1. Open your website in Talivia.
2. Go to **Settings → Integrations**.
3. Find the **GitHub** integration and select **Connect GitHub**.
4. Install the app on your GitHub account or organization and choose the repository for this website.

If you grant access to a single repository, it connects automatically and Talivia backfills up to 300 commits from the last 30 days. If you grant access to several repositories, pick the one that belongs to this website when you return to the settings page.

## Use commits to understand a change [#use-commits-to-understand-a-change]

When you notice a change on the chart:

1. Find the commits shown near the same time.
2. Hover over them to read what shipped.
3. Compare the deploy with the change in visitors or revenue.
4. Open a commit on GitHub when you want the full diff.

Commits provide context rather than guaranteed attribution. Use them together with referrers, campaigns, and revenue data to understand what most likely influenced the change.


---

# Track X mentions (https://talivia.com/docs/integrations/x-mentions)



When visitors or revenue suddenly increase, it is not always obvious what caused the change. X mention monitoring adds relevant conversations to your analytics chart, helping you understand whether people were discussing your product or website at the same time.

## Why track X mentions? [#why-track-x-mentions]

X mentions give useful context to your website analytics:

* Understand unexpected traffic and revenue spikes.
* Discover conversations about your product or website.
* See what people were saying when website activity changed.
* Find Posts that may be worth responding to or sharing.

## How it works [#how-it-works]

Talivia checks X for mentions of your product or website and shows matching Posts on the main analytics chart.

Hover over a mention on the chart to preview the conversation. Select it to see the complete list for that moment and open an original Post on X.

Because mentions appear alongside visitors and revenue, you can compare the conversation with what was happening on your website without switching between separate tools.

## Set up X mention monitoring [#set-up-x-mention-monitoring]

1. Open your website in Talivia.
2. Go to **Settings → Integrations**.
3. Find the **X** integration and select **Connect**.

That is all. Mention monitoring starts automatically after you connect the integration; there is no separate manual sync step.

Talivia uses the product name and website address already saved in your website settings, so there is nothing else to configure.

## Use mentions to understand a spike [#use-mentions-to-understand-a-spike]

When you notice a change on the chart:

1. Find any mention shown near the same time.
2. Hover over it to read the related Posts.
3. Compare the conversation with the change in visitors or revenue.
4. Open a relevant Post on X when you want to see the full conversation.

Mentions provide context rather than guaranteed attribution. Use them together with referrers, campaigns, and revenue data to understand what most likely influenced the change.


---

# Links (https://talivia.com/docs/links)



Links are redirect URLs that Talivia can track separately from a full website script install.

Create a link from **Links**, set a destination URL, and copy the generated URL.

```txt
https://talivia.com/q/abc123xyz
```

When someone opens it, Talivia records a link event and redirects to the destination.

## When to use links [#when-to-use-links]

* Newsletter links.
* Social bio links.
* Affiliate links.
* Sponsor cards.
* Campaign URLs where you cannot install the script.

## Reporting [#reporting]

Link reports use the same core analytics panels as websites: visitors, referrers, countries, devices, events, and date filters.

Screenshot placeholder: link edit form with destination URL and generated tracking link.


---

# Mobile app analytics (https://talivia.com/docs/mobile-analytics)



Talivia mobile SDKs send app activity to the same collector used by your website. Use the same **Website ID** and **hostname** as your web tracker to see web and app activity in one workspace. A mobile app does **not** use the browser `script.js` tracker; Expo Web still does.

| App framework           | SDK                     | Status                              | Guide                                               |
| ----------------------- | ----------------------- | ----------------------------------- | --------------------------------------------------- |
| React Native / Expo     | `@talivia/react-native` | Published on npm                    | [React Native](https://talivia.com/docs/mobile-analytics/react-native) |
| Flutter                 | `talivia_flutter`       | Published on pub.dev                | [Flutter](https://talivia.com/docs/mobile-analytics/flutter)           |
| Native iOS / Swift      | Talivia Swift package   | Public Swift Package Manager source | [Swift](https://talivia.com/docs/mobile-analytics/swift)               |
| Native Android / Kotlin | Talivia Android module  | Maven Central release pending       | [Android](https://talivia.com/docs/mobile-analytics/android)           |

## What to record [#what-to-record]

1. Call `screen()` when navigation changes. No SDK observes your router automatically.
2. Call `track()` after a meaningful product action, such as completed onboarding or feature use.
3. Call `identify()` after login with your stable account ID. Call `reset()` on logout.

Initialize only when your consent and privacy settings permit analytics collection. Do not put a private server API key in the mobile app.

## Measurement boundaries [#measurement-boundaries]

* The same Website ID puts web and app events in one workspace. Matching stable user IDs link known customer identity records, but current funnels still group by visitor token; they do not merge cross-device journeys.
* SDK queues hold at most 100 events **in memory**. App exit clears pending retries. Do not use them as durable offline storage.
* SDKs do not automatically track installs, deep-link campaign attribution, app-store purchases, or verified revenue. Send authoritative purchase data from a trusted backend or payment integration.
* If your app also has a website, keep the website tracker on web pages and the mobile SDK in native app code.

Explore the [mobile app analytics overview](https://talivia.com/mobile-app-analytics) for platform links and product context.


---

# Native Android and Kotlin (https://talivia.com/docs/mobile-analytics/android)



The native Android SDK is **in preparation**. Its Maven Central artifact `com.talivia:talivia-android` is **not published yet**. Do not add that coordinate as a remote dependency. This page shows the planned API so you can prepare your event design; installation steps will follow the release.

## Planned tracking API [#planned-tracking-api]

```kotlin
val analytics = Talivia(
    context = applicationContext,
    websiteId = "YOUR_WEBSITE_UUID",
    hostname = "example.com",
)

analytics.screen("Home")
analytics.track("signup_completed", mapOf("plan" to "pro"))
analytics.identify("your-stable-user-id")
// On logout: analytics.reset()
```

Call `screen()` when navigation changes and `track()` after a meaningful product action succeeds. The SDK sends on a worker thread. Use the same Website ID and hostname as your website for a shared workspace, and initialize only when your privacy settings permit collection.

Known identities can be linked with a stable account ID, but current funnels still group by visitor token across devices. The retry queue is in memory and capped at 100 events. Native install attribution and verified app purchases need separate trusted integrations.

[See Android analytics](https://talivia.com/mobile-app-analytics/android)


---

# Flutter (https://talivia.com/docs/mobile-analytics/flutter)



`talivia_flutter` supports Flutter apps on iOS and Android. It sends native app activity to the Talivia collector without a private API key in the app.

## Install [#install]

```sh
flutter pub add talivia_flutter
flutter pub add shared_preferences
```

## Initialize and track [#initialize-and-track]

```dart
import 'dart:io';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:talivia_flutter/talivia_flutter.dart';

final analytics = Talivia(
  websiteId: 'YOUR_WEBSITE_UUID',
  platform: Platform.isIOS ? 'ios' : 'android',
  preferences: await SharedPreferences.getInstance(),
  hostname: 'example.com',
);

await analytics.screen('Home');
await analytics.track('signup_completed', {'plan': 'pro'});
await analytics.identify('your-stable-user-id');
// On logout: await analytics.reset();
```

Call `screen()` when your Navigator or Router changes. Record events only after the relevant product action completes. Initialize when your app's consent and privacy settings permit collection.

Use the same Website ID, hostname, and stable account ID as your web tracker to inspect both sources in one workspace. Current funnels remain visitor-based across devices. Offline retries are memory-only, capped at 100, and lost when the app exits. App-store purchases and campaign attribution need separate trusted integrations.

[See Flutter analytics](https://talivia.com/mobile-app-analytics/flutter) · [View on pub.dev](https://pub.dev/packages/talivia_flutter)


---

# React Native and Expo (https://talivia.com/docs/mobile-analytics/react-native)



Use `@talivia/react-native` for native iOS and Android apps built with React Native or Expo. For Expo Web, use the [Expo Web installation guide](https://talivia.com/docs/installation-guides/expo) instead.

## Install [#install]

```sh
npm install @talivia/react-native
```

For Expo, also install the storage and UUID adapters:

```sh
npx expo install @react-native-async-storage/async-storage expo-crypto
```

## Initialize and track [#initialize-and-track]

```tsx
import AsyncStorage from '@react-native-async-storage/async-storage';
import * as Crypto from 'expo-crypto';
import { Platform } from 'react-native';
import { Talivia } from '@talivia/react-native';

const analytics = new Talivia({
  websiteId: 'YOUR_WEBSITE_UUID',
  host: 'https://talivia.com',
  hostname: 'example.com', // use your website domain for a shared workspace
  platform: Platform.OS === 'ios' ? 'ios' : 'android',
  storage: AsyncStorage,
  uuid: prefix => `${prefix}_${Crypto.randomUUID()}`,
});

await analytics.init();
await analytics.screen('Home');
await analytics.track('signup_completed', { plan: 'pro' });
await analytics.identify('your-stable-user-id');
// On logout: await analytics.reset();
```

Call `screen()` from your React Navigation or Expo Router change callback. Call `track()` only after the action succeeds. For bare React Native, provide a storage adapter and secure UUID generator appropriate to your app; runtimes with `crypto.randomUUID` or `crypto.getRandomValues` do not need an explicit UUID adapter.

Initialize only when consent permits collection. Call `flush()` when connectivity returns if you want to retry queued events before the next app event. The retry queue is memory-only and capped at 100 events.

Using the same Website ID and hostname as web makes both sources visible in one Talivia workspace. `identify()` links known account identity records when the stable ID matches; current funnels still group by visitor token across devices. Install attribution and purchases are not captured automatically. Send verified revenue from your backend.

[See React Native analytics](https://talivia.com/mobile-app-analytics/react-native) · [View package source](https://github.com/talivia-group/react-native)


---

# Swift and iOS (https://talivia.com/docs/mobile-analytics/swift)



Add the public Talivia package through Swift Package Manager in Xcode. Select version `0.1.0` from:

```text
https://github.com/talivia-group/swift.git
```

In another Swift package, add `.package(url: "https://github.com/talivia-group/swift.git", from: "0.1.0")` and depend on the `Talivia` library product.

## Initialize and track [#initialize-and-track]

```swift
import Talivia

let analytics = try Talivia(
    websiteId: "YOUR_WEBSITE_UUID",
    hostname: "example.com"
)

try await analytics.screen("Home")
try await analytics.track("signup_completed", data: ["plan": .string("pro")])
try await analytics.identify("your-stable-user-id")
// On logout: analytics.reset()
```

The methods are main-actor isolated. Call `screen()` when your app shows another screen; the package does not observe SwiftUI or UIKit navigation automatically. Record product events after the action occurs, and initialize only when collection is permitted by your privacy settings.

Use the same Website ID and hostname as your website for a shared workspace. Matching stable IDs link known account identity records, while current funnels remain visitor-based across devices. The in-memory retry queue holds up to 100 events. Verify purchase revenue on a trusted server; app-store purchase tracking is not automatic.

[See iOS analytics](https://talivia.com/mobile-app-analytics/swift) · [View package source](https://github.com/talivia-group/swift)


---

# Performance (https://talivia.com/docs/performance)



Performance collection records Web Vitals as analytics events. Enable it when you want to connect page speed to visitors, sessions, and revenue.

## Enable Web Vitals [#enable-web-vitals]

```html
<script
  defer
  src="https://talivia.com/script.js"
  data-website-id="YOUR_WEBSITE_ID"
  data-performance="true"
></script>
```

Talivia can collect:

* `LCP` Largest Contentful Paint.
* `INP` Interaction to Next Paint.
* `CLS` Cumulative Layout Shift.
* `FCP` First Contentful Paint.
* `TTFB` Time to First Byte.

## Report [#report]

Open **Performance** to review pages with slow loading or interaction issues. Use filters to inspect a single path, browser, country, or traffic source.

## Practical workflow [#practical-workflow]

Start with pages that produce revenue. A slow pricing or checkout page matters more than a slow low-intent content page.


---

# Pixels (https://talivia.com/docs/pixels)



Pixels are lightweight URLs that record an event when requested. They are useful when a full JavaScript tracker is not available.

Create a pixel from **Pixels** and copy the generated URL.

```txt
https://talivia.com/p/abc123xyz
```

## Common uses [#common-uses]

* Email opens where images are allowed.
* Lightweight campaign impressions.
* Embedded assets in third-party pages.

## Limitations [#limitations]

Pixel requests do not have the same browser context as the JavaScript tracker. You may still see request-derived information like country, user agent, and timestamp, but not full client-side route behavior.


---

# Revenue (https://talivia.com/docs/revenue)



Revenue attribution shows which sessions, sources, pages, campaigns, and search queries produced money. The settings screen connects the payment account; the provider guides explain the checkout-specific implementation.

## Choose a revenue source [#choose-a-revenue-source]

| Source             | Use it when                                                                  | Setup guide                                         |
| ------------------ | ---------------------------------------------------------------------------- | --------------------------------------------------- |
| Stripe             | Checkout, Payment Links, invoices, or subscriptions run through Stripe       | [Stripe](https://talivia.com/docs/revenue-guides/stripe)               |
| Yolfi              | Payments and subscriptions run through Yolfi                                 | [Yolfi](https://talivia.com/docs/revenue-guides/yolfi)                 |
| Dodo Payments      | You use Dodo Payment Links or Checkout Sessions                              | [Dodo Payments](https://talivia.com/docs/revenue-guides/dodo-payments) |
| Manual Payment API | Your backend confirms revenue through a custom or unsupported payment system | [Manual Payment API](https://talivia.com/docs/revenue-guides/manual)   |

## How setup is divided [#how-setup-is-divided]

1. In **Website settings → Payments**, select the provider and connect its API key.
2. Open the provider guide from the final **Link payments with traffic** step.
3. Follow the checkout path that matches your implementation and make a test payment.
4. Confirm the payment has a source and session in Talivia.

The provider connection imports and receives revenue. Session metadata or a tracked return URL supplies the attribution signal that connects that revenue to the visit.

Connection and attribution are separate checks. A provider can be connected successfully while a payment remains unattributed if checkout did not include a Talivia session signal.

## Refunds [#refunds]

Refunds are shown as reversed revenue in charts. Talivia keeps the original paid context visible so you can see the money that would have counted and the amount refunded.

Screenshot placeholder: revenue chart with paid and refunded bars.


---

# Dodo Payments (https://talivia.com/docs/revenue-guides/dodo-payments)



Payment Link on your site

Use a normal Dodo link or linked button. Talivia handles attribution automatically.

Checkout Session

Add one Talivia session value when your backend creates the Dodo checkout.

Shared Payment Link

The payment is recorded, but a buyer who skips your site may be unattributed.

Test and troubleshoot Dodo Payments

Check the API environment, managed webhook, checkout metadata, and refunds.


---

# Dodo Checkout Session (https://talivia.com/docs/revenue-guides/dodo-payments/checkout-session)



Use this option when your backend creates a Dodo Checkout Session. It also covers Dodo Overlay and Inline Checkout because both start from a Checkout Session.

Connect your account in **Website settings → Revenue → Dodo Payments**, then pass the current Talivia session into the checkout metadata.

## Add the session to checkout metadata [#add-the-session-to-checkout-metadata]

Read the Talivia session cookie on the backend and merge it into the `metadata` object in your existing Dodo call.

```javascript title="Create a Dodo Checkout Session"
const taliviaSessionId = request.cookies.get('talivia_session_id')?.value;

const checkout = await dodo.checkoutSessions.create({
  product_cart,
  return_url: 'https://your-site.com/thanks',
  metadata: {
    // Keep your existing metadata fields here.
    ...(taliviaSessionId && { talivia_session_id: taliviaSessionId }),
  },
});
```

`metadata` is Dodo's standard metadata object. Keep any fields you already send and add only `talivia_session_id`. Talivia reads that value from the verified payment event and handles attribution.

## Checkout API on another origin [#checkout-api-on-another-origin]

If browser code calls a checkout API on another origin, include the opaque session value in that request:

```javascript title="Browser checkout handoff"
const sessionId = window.talivia.getSessionId();

await fetch('https://api.your-site.com/create-checkout', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ sessionId }),
});
```

Validate the request normally and place the received value in `metadata.talivia_session_id` when the backend creates the Checkout Session. The session ID is an attribution identifier, not authentication.

See [Dodo Checkout Sessions](https://docs.dodopayments.com/developer-resources/checkout-session) for the provider-side checkout options.

No manual webhook setup is needed. Talivia configures and verifies the Dodo webhook when you connect the provider.


---

# Dodo Payment Link on your site (https://talivia.com/docs/revenue-guides/dodo-payments/payment-link-on-your-site)



Use this option when a customer opens a Dodo Payment Link from your website. First connect the account in **Website settings → Revenue → Dodo Payments**.

## Add the link to a tracked page [#add-the-link-to-a-tracked-page]

Use the complete Payment Link copied from Dodo in a normal `<a>` link or a linked button. No Talivia-specific checkout code is needed.

```html title="Dodo Payment Link"
<a href="https://checkout.dodopayments.com/buy/YOUR_PRODUCT_ID?redirect_url=https%3A%2F%2Fyour-site.com%2Fthanks">
  Buy now
</a>
```

The Talivia tracker adds the current session before opening checkout and preserves the parameters already present in the link. When Dodo reports the successful payment, Talivia matches it with the originating visit.

Automatic attribution applies when the customer clicks a normal Dodo link on a page where the Talivia tracker is running. If your application creates a Checkout Session through the Dodo API, use the [Checkout Session guide](https://talivia.com/docs/revenue-guides/dodo-payments/checkout-session) instead.

See [Dodo Payment Links](https://docs.dodopayments.com/developer-resources/integration-guide) for provider-side link configuration.

No manual webhook setup is needed. Connecting Dodo Payments in Website settings configures the webhook and imports the available revenue history.


---

# Shared Dodo Payment Link (https://talivia.com/docs/revenue-guides/dodo-payments/shared-payment-link)



No checkout code is required when you share a Dodo Payment Link directly. Connect Dodo Payments in **Website settings → Revenue** so Talivia can receive and record successful payments.

## When the payment is unattributed [#when-the-payment-is-unattributed]

If a buyer opens Dodo directly from an email, chat, social post, marketplace, or QR code without visiting your website, there is no Talivia website session to attach. The payment is still recorded, but it can appear as **Unattributed**.

This is expected: the provider webhook proves that the payment happened, but it does not create a website visit retroactively.

## Recommended flow [#recommended-flow]

For reliable attribution, share a landing page on your site instead of the raw Dodo checkout URL. Place the Payment Link on that tracked page:

```html title="Tracked landing page"
<a href="https://checkout.dodopayments.com/buy/YOUR_PRODUCT_ID">
  Buy now
</a>
```

Talivia can then attach the visitor's current session when they click **Buy**. Continue with [Payment Link on your site](https://talivia.com/docs/revenue-guides/dodo-payments/payment-link-on-your-site) for the complete behavior.

No manual webhook setup is needed. Direct and attributed Dodo payments use the same provider connection configured in Website settings.


---

# Test and troubleshoot Dodo Payments (https://talivia.com/docs/revenue-guides/dodo-payments/testing-and-troubleshooting)



Use the [shared payment testing setup](https://talivia.com/docs/revenue-guides/testing-payment-providers) to keep test revenue separate from production, then apply the Dodo-specific checks below.

## Connect the test account [#connect-the-test-account]

Create an API key with write access in the Dodo test environment and connect it to your sandbox Talivia website. Talivia detects whether the key belongs to Dodo Test or Live, then uses the matching API to validate the business, import available history, and create the webhook.

There is no Dodo environment selector in Talivia. If a current Dodo key does not contain an environment prefix, Talivia validates it against the provider environments and stores the successful connection.

## Minimum test matrix [#minimum-test-matrix]

| Scenario                               | Expected Talivia result                               |
| -------------------------------------- | ----------------------------------------------------- |
| Payment Link clicked on a tracked page | Payment matched to the originating session            |
| API-created Checkout Session           | Payment matched through `metadata.talivia_session_id` |
| Overlay or Inline Checkout             | Same result as its underlying Checkout Session        |
| Link opened without visiting your site | Payment recorded as **Unattributed**                  |
| Full or partial refund                 | Original payment remains and net revenue is reduced   |
| Repeated webhook                       | No duplicate payment or refund                        |

## The connection fails [#the-connection-fails]

* **Rejected in both environments:** copy a new API key from Dodo and try again.
* **Webhook creation is forbidden:** enable write access for the key.
* **No business is found:** confirm the key belongs to a Dodo account with an available business or brand.

Reconnecting updates the managed endpoint for the Talivia webhook URL. When the account or environment changes, Talivia imports the new history and removes the previous managed endpoint.

## No payment appears [#no-payment-appears]

In the Dodo webhook settings, confirm the Talivia endpoint is enabled and the `payment.succeeded` delivery returned a successful response. Refund updates require `refund.succeeded`.

If delivery is missing, reconnect Dodo so Talivia can repair the webhook and retrieve its signing secret. If delivery is rejected, confirm the event came from the same Dodo environment as the connected key.

## The payment is unattributed [#the-payment-is-unattributed]

* **Payment Link:** open it through a normal link on a page where the Talivia tracker is running.
* **Checkout Session, Overlay, or Inline Checkout:** add the current session as `metadata.talivia_session_id` when your backend creates the Checkout Session.
* **Shared raw link:** an unattributed payment is expected when the buyer never visits your tracked website.

Do not use the Talivia session id as authentication. It is only an opaque attribution value.


---

# LemonSqueezy (https://talivia.com/docs/revenue-guides/lemonsqueezy)



Checkout Links

Hosted checkout or a standard Lemon.js overlay link on your tracked site.

Checkout API

Create custom checkout on your backend and pass the Talivia session explicitly.

Return URL fallback

Match an order when metadata cannot be added to the original checkout.

Subscriptions and renewals

Preserve the first attributed checkout across recurring payments and lifecycle changes.

Test and troubleshoot LemonSqueezy

Verify the key mode, managed webhook, custom data, subscriptions, and refunds.


---

# LemonSqueezy Checkout API (https://talivia.com/docs/revenue-guides/lemonsqueezy/checkout-api)



Use this flow when your backend calls `POST /v1/checkouts` and returns the generated checkout URL to the browser.

## Send the session to your backend [#send-the-session-to-your-backend]

Read the current session on the tracked page and include it in your own checkout request:

```javascript title="Start checkout from the browser"
const sessionId = window.talivia.getSessionId();

const response = await fetch('/api/create-checkout', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ sessionId }),
});

const { checkoutUrl } = await response.json();
window.location.assign(checkoutUrl);
```

Treat the session ID only as attribution context. Validate the customer, product, price, and authorization independently on your backend.

## Add custom checkout data [#add-custom-checkout-data]

Merge the received value into `attributes.checkout_data.custom` in the LemonSqueezy request:

```javascript title="Create the LemonSqueezy checkout"
const checkout = await fetch('https://api.lemonsqueezy.com/v1/checkouts', {
  method: 'POST',
  headers: {
    Accept: 'application/vnd.api+json',
    'Content-Type': 'application/vnd.api+json',
    Authorization: `Bearer ${process.env.LEMONSQUEEZY_API_KEY}`,
  },
  body: JSON.stringify({
    data: {
      type: 'checkouts',
      attributes: {
        checkout_data: {
          custom: {
            talivia_session_id: sessionId,
          },
        },
      },
      relationships: {
        store: { data: { type: 'stores', id: process.env.LEMONSQUEEZY_STORE_ID } },
        variant: { data: { type: 'variants', id: variantId } },
      },
    },
  }),
}).then(response => response.json());

return Response.json({ checkoutUrl: checkout.data.attributes.url });
```

LemonSqueezy copies custom checkout data to `meta.custom_data` in the signed webhook. This works for hosted custom checkouts and programmatically opened overlays.

Keep the LemonSqueezy API key on the server and preserve any other custom fields your application already sends.


---

# LemonSqueezy Checkout Links (https://talivia.com/docs/revenue-guides/lemonsqueezy/checkout-links)



Use this flow when a customer clicks a reusable LemonSqueezy Checkout Link on a page where the Talivia tracker is installed.

## Add the link to your site [#add-the-link-to-your-site]

Use the original share URL containing `/checkout/buy/`. Do not copy the single-use cart URL created after checkout opens.

```html title="Hosted LemonSqueezy checkout"
<a href="https://YOUR_STORE.lemonsqueezy.com/checkout/buy/VARIANT_ID">
  Buy now
</a>
```

Talivia adds the current session without removing discount, quantity, or other existing query parameters:

```text
checkout[custom][talivia_session_id]=s_...
```

LemonSqueezy returns this value as `meta.custom_data.talivia_session_id` in order and subscription webhook events. Talivia uses it to connect the revenue to the originating visit.

## Checkout overlay [#checkout-overlay]

The same automatic behavior works when a normal Checkout Link is used as a Lemon.js overlay button:

```html title="Lemon.js overlay link"
<a
  class="lemonsqueezy-button"
  href="https://YOUR_STORE.lemonsqueezy.com/checkout/buy/VARIANT_ID"
>
  Buy now
</a>
```

The link must still be a standard anchor on the tracked page. If your application creates a custom checkout or calls `LemonSqueezy.Url.Open()` with a URL generated elsewhere, continue with [Checkout API](https://talivia.com/docs/revenue-guides/lemonsqueezy/checkout-api).

No manual webhook setup is needed. Connecting LemonSqueezy in Website settings creates the signed order, subscription, and refund webhook.


---

# LemonSqueezy Return URL Fallback (https://talivia.com/docs/revenue-guides/lemonsqueezy/return-url)



Direct session metadata is the strongest attribution method. Use the return URL only when you cannot modify the checkout link or the API request.

## Add the order ID to the return link [#add-the-order-id-to-the-return-link]

In the LemonSqueezy product settings, set the confirmation modal button link to a tracked page and include the supported `order_id` variable:

```text title="Confirmation button URL"
https://your-site.com/thanks?order_id=[order_id]
```

After payment, LemonSqueezy replaces `[order_id]` with the real order ID. When the customer opens that page, the Talivia tracker records the order reference and matches it with the verified `order_created` webhook.

## Limits of return attribution [#limits-of-return-attribution]

* The tracker must be installed on the return page.
* The customer must click the confirmation button and return in the same browser.
* If the customer opened a shared checkout without first visiting your site, Talivia can record the payment but there is no earlier acquisition session to recover.
* Do not use the return page to fulfil the order; the signed webhook remains the payment source of truth.

For links rendered on your tracked website, use [Checkout Links](https://talivia.com/docs/revenue-guides/lemonsqueezy/checkout-links) instead. For server-created checkout, use [Checkout API](https://talivia.com/docs/revenue-guides/lemonsqueezy/checkout-api).


---

# LemonSqueezy Subscriptions and Renewals (https://talivia.com/docs/revenue-guides/lemonsqueezy/subscriptions-and-renewals)



Attribute the first subscription checkout with the same Talivia session field used for a one-time order. Use automatic decoration for a standard [Checkout Link](https://talivia.com/docs/revenue-guides/lemonsqueezy/checkout-links), or set `checkout_data.custom.talivia_session_id` through the [Checkout API](https://talivia.com/docs/revenue-guides/lemonsqueezy/checkout-api).

LemonSqueezy includes that custom data in the initial order and subscription webhooks. Talivia stores the LemonSqueezy customer and subscription relationship so later renewals can stay connected even though no new browser checkout occurs.

## Events Talivia maintains [#events-talivia-maintains]

The managed webhook processes:

* subscription creation and updates;
* cancellation, resumption, pause, unpause, and expiration;
* successful, failed, and recovered subscription payments;
* subscription payment refunds.

Successful renewal invoices become new revenue payments. Failed payments update subscription state without creating paid revenue, and refunds reduce the original payment's net revenue.

## Keep the customer relationship stable [#keep-the-customer-relationship-stable]

Do not create a new LemonSqueezy customer for every renewal or plan change. Keeping the provider customer and subscription IDs stable lets Talivia reuse the attribution established by the initial checkout.

If a renewal is unattributed, first confirm the initial checkout contained `meta.custom_data.talivia_session_id`, then confirm later events use the same LemonSqueezy customer and subscription.


---

# Test and troubleshoot LemonSqueezy (https://talivia.com/docs/revenue-guides/lemonsqueezy/testing-and-troubleshooting)



Use the [shared payment testing setup](https://talivia.com/docs/revenue-guides/testing-payment-providers) to keep sandbox revenue separate from production, then apply the LemonSqueezy checks below.

## Connect test mode [#connect-test-mode]

1. Create or select a LemonSqueezy store in test mode.
2. Create an API key while LemonSqueezy is in test mode.
3. Connect that Store ID and API key to your sandbox Talivia website.

Talivia detects the API key mode and creates the webhook with the matching `test_mode` value. There is no environment selector in Talivia.

## Minimum test matrix [#minimum-test-matrix]

| Scenario                    | Expected Talivia result                                 |
| --------------------------- | ------------------------------------------------------- |
| One-time order              | One payment with the order amount and currency          |
| Subscription signup         | Initial payment and an active subscription              |
| Subscription renewal        | One new payment connected to the same customer          |
| Failed or recovered renewal | Subscription state changes without duplicate revenue    |
| Full or partial refund      | The original payment remains and net revenue is reduced |
| Repeated webhook            | No duplicate payment or subscription                    |

## The connection fails [#the-connection-fails]

* Confirm the API key can read the Store ID you entered.
* Confirm both values were copied from the same LemonSqueezy environment.
* Create a new API key if LemonSqueezy returns `401` or `403`.
* Reconnect after rotating the key; Talivia creates a new signed webhook and removes the previous managed endpoint.

## No payment appears [#no-payment-appears]

Open **Settings → Webhooks** in LemonSqueezy and find the Talivia endpoint for the connected store. Confirm the delivery succeeded and that the event is one Talivia processes, such as `order_created`, `subscription_payment_success`, `order_refunded`, or `subscription_payment_refunded`.

If the endpoint is missing or has the wrong `test_mode`, reconnect the provider from Talivia with the API key for the intended environment.

## The payment is unattributed [#the-payment-is-unattributed]

* **Standard link or overlay:** follow [Checkout Links](https://talivia.com/docs/revenue-guides/lemonsqueezy/checkout-links) and confirm checkout started from a tracked page.
* **Server-created checkout:** follow [Checkout API](https://talivia.com/docs/revenue-guides/lemonsqueezy/checkout-api) and confirm `checkout_data.custom.talivia_session_id` was included.
* **Metadata is unavailable:** configure the [Return URL fallback](https://talivia.com/docs/revenue-guides/lemonsqueezy/return-url).

For the first two flows, inspect the delivered webhook and confirm the session appears in `meta.custom_data.talivia_session_id`.


---

# Manual Payment API (https://talivia.com/docs/revenue-guides/manual)



Use the Manual Payment API when revenue comes from a custom checkout, bank transfer, crypto processor, app store, invoice system, or another provider that Talivia does not connect to directly.

## Create an API key [#create-an-api-key]

Open **Website settings -> API keys** and generate a key. Talivia creates it for the current
website.

Copy the secret immediately because it is shown only once. Store it only on your backend and do not
expose it in browser code.

## Send a payment [#send-a-payment]

Send payment events to Talivia after your backend confirms the money was received.

Before checkout, send `window.talivia.getSessionId()` to your backend and keep it with the order as `sessionId`.

```javascript title="Record a confirmed payment"
await fetch('https://talivia.com/api/payments/manual', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-talivia-api-key': process.env.TALIVIA_API_KEY,
  },
  body: JSON.stringify({
    websiteId: 'YOUR_WEBSITE_ID',
    transactionId: 'order_123',
    amount: 49,
    currency: 'USD',
    providerName: 'manual',
    providerPaymentId: 'payment_123',
    providerCustomerId: 'customer_123',
    sessionId: order.sessionId,
  }),
});
```

Use stable ids. `transactionId` should be unique for the payment in your system. Reuse the same id if you retry the request.

## Supported attribution fields [#supported-attribution-fields]

Send the session field when possible:

* `sessionId`
* `providerCustomerId`
* `externalCustomerId`
* `email`
* `emailHash`

Talivia uses `sessionId` to connect the payment to the exact visitor journey. Customer fields can reconnect later renewals after the initial payment has been matched.

## Verify [#verify]

1. Send a test payment from your backend.
2. Open Talivia payments for the website.
3. Confirm the amount, currency, provider name, and transaction id.
4. Open the visitor profile and verify that the spend appears in the matched visitor journey.


---

# Polar (https://talivia.com/docs/revenue-guides/polar)



Checkout API

Create a checkout on your backend and attach the Talivia session directly.

Checkout Links

Use a no-code Polar link and match the payment when the buyer returns.

Embedded Checkout

Open Polar inside your site while keeping the same return-based attribution.

Subscriptions and renewals

Keep the original customer identity across recurring orders and lifecycle changes.

Other methods

Attribute custom integrations through a stable Polar customer identity.

Test and troubleshoot Polar

Check token permissions, sandbox checkout, attribution, subscriptions, and refunds.


---

# Polar Checkout API (https://talivia.com/docs/revenue-guides/polar/checkout-api)



This is the most reliable Polar integration. Talivia receives the same session ID in the signed `order.paid` webhook and can attribute the order without depending on a return visit.

## Send the Talivia session to your backend [#send-the-talivia-session-to-your-backend]

```javascript title="Browser checkout handoff"
const sessionId = window.talivia.getSessionId();

const response = await fetch('/api/create-polar-checkout', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ sessionId }),
});

const { url } = await response.json();
window.location.assign(url);
```

The session ID is an attribution identifier, not authentication. Validate the product and signed-in user on your backend as usual.

## Add metadata when checkout is created [#add-metadata-when-checkout-is-created]

Keep the Polar access token on the server. Polar copies checkout metadata to the resulting order and subscription, so one field covers both one-time and recurring products.

```javascript title="Create a Polar Checkout Session"
import { Polar } from '@polar-sh/sdk';

const polar = new Polar({
  accessToken: process.env.POLAR_ACCESS_TOKEN,
});

const checkout = await polar.checkouts.create({
  products: [process.env.POLAR_PRODUCT_ID],
  successUrl:
    'https://your-site.com/thanks?checkout_id={CHECKOUT_ID}',
  returnUrl: 'https://your-site.com/pricing',
  externalCustomerId: user.id,
  customerEmail: user.email,
  metadata: {
    talivia_session_id: sessionId,
  },
});

return Response.json({ url: checkout.url });
```

`externalCustomerId` should be a stable ID from your own application. It gives Talivia a second matching signal for future renewals. Keep `checkout_id={CHECKOUT_ID}` in the success URL as a useful fallback and debugging signal.


---

# Polar Checkout Links (https://talivia.com/docs/revenue-guides/polar/checkout-links)



Checkout Links do not let your server attach fresh Talivia metadata for every buyer. Use Polar's success URL placeholder so Talivia can connect the completed checkout to the browser session when the buyer returns.

## Configure the link [#configure-the-link]

1. Create or edit the Checkout Link in Polar.
2. Set its success URL to a tracked page on your site.
3. Include the exact `checkout_id={CHECKOUT_ID}` query parameter.

```text title="Success URL"
https://your-site.com/thanks?checkout_id={CHECKOUT_ID}
```

Place the link on a page where the Talivia tracker is installed.

```html title="Checkout Link"
<a href="https://buy.polar.sh/polar_cl_YOUR_LINK">Buy now</a>
```

After payment, the Polar webhook records the order. The return page sends the checkout ID from the URL to Talivia, which supplies the session-side match.

Shared links have a natural limit. If a buyer opens the link from email or social media and never visits your tracked site, Talivia records the revenue but cannot invent a traffic source. The payment remains unattributed unless customer identity provides another match.

For logged-in products, also call `identify` with the same application customer ID used by Polar. See [Other methods](https://talivia.com/docs/revenue-guides/polar/other-methods).


---

# Polar Embedded Checkout (https://talivia.com/docs/revenue-guides/polar/embedded-checkout)



Polar Embedded Checkout is a Checkout Link presented in an iframe. Attribution follows the same rule as a normal link: keep the checkout success URL on your tracked domain with `checkout_id={CHECKOUT_ID}`.

## Add the checkout trigger [#add-the-checkout-trigger]

```html title="Embedded Checkout"
<a
  href="https://buy.polar.sh/polar_cl_YOUR_LINK"
  data-polar-checkout
  data-polar-checkout-theme="dark"
>
  Buy now
</a>

<script
  src="https://cdn.jsdelivr.net/npm/@polar-sh/checkout@0.1/dist/embed.global.js"
  defer
  data-auto-init
></script>
```

Configure the underlying Checkout Link success URL before using the embed:

```text title="Success URL"
https://your-site.com/thanks?checkout_id={CHECKOUT_ID}
```

## React or programmatic embed [#react-or-programmatic-embed]

```javascript title="Open checkout programmatically"
import { PolarEmbedCheckout } from '@polar-sh/checkout/embed';

await PolarEmbedCheckout.create(
  'https://buy.polar.sh/polar_cl_YOUR_LINK',
  'dark',
);
```

Do not treat the client-side `success` event as the source of truth for revenue. Talivia records revenue from Polar's signed `order.paid` webhook and uses the browser return only for attribution.

If you create an embedded Checkout Session through the API instead of a static link, set `embedOrigin` to your site's origin and use [Checkout API metadata](https://talivia.com/docs/revenue-guides/polar/checkout-api) for the strongest match.


---

# Other Polar methods (https://talivia.com/docs/revenue-guides/polar/other-methods)



Some integrations create customers or orders through another billing layer and cannot pass `talivia_session_id`. In that case, link the visitor to the same customer identity that appears in Polar webhooks.

## Use a stable external customer ID [#use-a-stable-external-customer-id]

Set Polar's `external_customer_id` to your own immutable user ID whenever your integration supports it. Then identify the signed-in visitor with that value.

```javascript title="Identify the application customer"
window.talivia.identify(user.id, {
  email: user.email,
  externalCustomerId: user.id,
  providerName: 'polar',
});
```

If your backend already knows the Polar customer UUID, include it too.

```javascript title="Identify the Polar customer"
window.talivia.identify(user.id, {
  email: user.email,
  externalCustomerId: user.id,
  providerName: 'polar',
  polarCustomerId: 'YOUR_POLAR_CUSTOMER_ID',
});
```

Use [Checkout API](https://talivia.com/docs/revenue-guides/polar/checkout-api) whenever you control checkout creation. Direct session metadata is deterministic; customer identity is a fallback for checkouts and the primary signal for renewals.

If none of session metadata, a checkout return, external customer ID, Polar customer ID, or matching verified email is available, Talivia will still record the order but show it as unattributed.


---

# Polar subscriptions and renewals (https://talivia.com/docs/revenue-guides/polar/subscriptions-and-renewals)



Talivia listens for Polar subscription lifecycle events and records paid renewal orders from `order.paid`. The first checkout should carry both a Talivia session ID and a stable application customer ID.

```javascript title="Create a recurring checkout"
const checkout = await polar.checkouts.create({
  products: [process.env.POLAR_RECURRING_PRODUCT_ID],
  successUrl:
    'https://your-site.com/thanks?checkout_id={CHECKOUT_ID}',
  externalCustomerId: user.id,
  customerEmail: user.email,
  metadata: {
    talivia_session_id: sessionId,
  },
});
```

Polar copies checkout metadata to the created subscription. Talivia stores the subscription state and reuses the customer identity for later orders where there is no new browser session.

## Identify signed-in customers [#identify-signed-in-customers]

Call `identify` after login and again when you learn the Polar customer ID.

```javascript title="Link the Polar customer"
window.talivia.identify(user.id, {
  email: user.email,
  externalCustomerId: user.id,
  providerName: 'polar',
  polarCustomerId: polarCustomer.id,
});
```

The external ID is usually enough when you set the same value during checkout. Adding the Polar customer ID makes matching more resilient.

## What Talivia imports [#what-talivia-imports]

* the initial paid order and later paid renewals;
* cumulative full or partial refunds;
* subscription creation and status changes;
* active subscription context during the initial connection backfill.

Trials without a paid order are stored as subscription state, not revenue.


---

# Test and troubleshoot Polar (https://talivia.com/docs/revenue-guides/polar/testing-and-troubleshooting)



Start with the [shared payment testing setup](https://talivia.com/docs/revenue-guides/testing-payment-providers), then use the Polar-specific connection and attribution checks below.

## Connection checklist [#connection-checklist]

In Polar, create an Organization Access Token for the correct organization with these permissions:

* Checkout Read;
* Orders Read;
* Organization Read;
* Products Read;
* Subscription Read;
* Webhook Write.

In **Website settings → Revenue → Polar**, paste the token, then select **Connect Polar**. Talivia detects the token's organization and whether it belongs to production or sandbox, validates every permission, creates the signed webhook, imports the previous 30 days of orders, and syncs subscription state.

You do not need to copy a webhook secret or create an OAuth application.

## End-to-end test [#end-to-end-test]

1. Create a separate Talivia website and connect a Polar Sandbox organization there.
2. Open checkout from a tracked browser session.
3. Complete an order with Polar's sandbox payment flow.
4. Confirm the payment appears in Talivia with provider **Polar**.
5. Open the payment and verify its session, source, entry page, and amount.
6. Create a refund in Polar and confirm the same payment's refunded amount is updated.

## Payment is unattributed [#payment-is-unattributed]

For Checkout API, inspect the created checkout and confirm `metadata.talivia_session_id` equals the value returned by `window.talivia.getSessionId()`.

For Checkout Links and Embedded Checkout, confirm the Polar success URL is a tracked page and contains:

```text
checkout_id={CHECKOUT_ID}
```

For subscriptions or custom flows, confirm Polar's customer `external_id` matches the `externalCustomerId` sent to `window.talivia.identify`.

## Connection fails [#connection-fails]

* **Organization not found:** confirm the token has Organization Read and was created as an Organization Access Token.
* **Permission error:** recreate or update the token with every permission in the checklist.
* **Webhook error:** confirm Webhook Write is enabled and reconnect; Talivia will repair or recreate its endpoint.
* **Production versus sandbox:** Talivia detects the environment from the token automatically. Keep
  sandbox and production in separate Talivia websites so their revenue is not mixed.


---

# Stripe (https://talivia.com/docs/revenue-guides/stripe)



Session signal, visitor report. The session ID is the checkout attribution signal passed to Stripe. After Talivia matches the payment, the **Visitors** report rolls it into the visitor's journey and spend. Keep using `talivia_session_id` or the documented `client_reference_id`; the visitor-centred interface does not change the integration field.

Checkout Sessions

Hosted or embedded Stripe Checkout. The best default for most new integrations.

Payment Links

No-code checkout through a 

buy.stripe.com

 link.

Payment Intents

A custom checkout that creates Payment Intents directly.

Subscriptions and invoices

Recurring plans, renewals, and invoice payments.

Other methods

Custom billing layers, third-party processors, or unsupported Stripe objects.

Test and troubleshoot Stripe

Verify events, attribution, subscriptions, refunds, and Payment Links.


---

# Stripe Checkout Sessions (https://talivia.com/docs/revenue-guides/stripe/checkout-sessions)



Use this integration for Stripe-hosted Checkout and for embedded checkout built with the Checkout Sessions API.

## Pass the Talivia session to your backend [#pass-the-talivia-session-to-your-backend]

If your checkout request starts in browser code, include the current opaque session ID.

```javascript title="Browser checkout handoff"
const sessionId = window.talivia.getSessionId();

const response = await fetch('/api/create-checkout', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ sessionId }),
});

const { url } = await response.json();
window.location.assign(url);
```

When checkout is created on the same site as the Talivia tracker, your backend can read the `talivia_session_id` first-party cookie instead. Validate request input normally; the session ID is an attribution identifier, not authentication.

## One-time payment [#one-time-payment]

Set metadata on both the Checkout Session and its underlying Payment Intent so the attribution context remains available on both objects. Talivia records Checkout-backed payments from the Checkout Session event. Checkout-backed Payment Intents whose order reference begins with `cs_` are ignored to prevent duplicate revenue.

```javascript title="Create a one-time Checkout Session"
const session = await stripe.checkout.sessions.create({
  mode: 'payment',
  line_items: [{ price: 'price_123', quantity: 1 }],
  success_url:
    'https://your-site.com/thanks?session_id={CHECKOUT_SESSION_ID}',
  cancel_url: 'https://your-site.com/pricing',
  metadata: {
    talivia_session_id: sessionId,
  },
  payment_intent_data: {
    metadata: {
      talivia_session_id: sessionId,
    },
  },
});
```

Top-level `metadata` appears on `checkout.session.completed`. `payment_intent_data.metadata` is copied to the Payment Intent and appears on `payment_intent.succeeded`.

## Subscription checkout [#subscription-checkout]

For recurring plans, copy the session ID to the Subscription so renewals and lifecycle events keep the original customer context.

```javascript title="Create a subscription Checkout Session"
const session = await stripe.checkout.sessions.create({
  mode: 'subscription',
  line_items: [{ price: 'price_monthly', quantity: 1 }],
  success_url:
    'https://your-site.com/thanks?session_id={CHECKOUT_SESSION_ID}',
  cancel_url: 'https://your-site.com/pricing',
  metadata: {
    talivia_session_id: sessionId,
  },
  subscription_data: {
    metadata: {
      talivia_session_id: sessionId,
    },
  },
});
```

Continue with [Subscriptions and invoices](https://talivia.com/docs/revenue-guides/stripe/subscriptions-and-invoices) for renewals, failed invoices, and customer identity.

## Delayed payment methods [#delayed-payment-methods]

Bank debits, vouchers, and some local payment methods can complete Checkout before money is confirmed. Talivia does not record an unpaid completed session as revenue. It waits for Stripe's asynchronous success event and imports only sessions whose `payment_status` is `paid`.

## Return URL fallback [#return-url-fallback]

Keep `{CHECKOUT_SESSION_ID}` in the success URL even when metadata is present. The return visit gives Talivia a second matching signal and helps diagnose missing metadata.


---

# Other Stripe methods (https://talivia.com/docs/revenue-guides/stripe/other-methods)



Choose the narrowest integration that still gives Talivia a server-verified payment.

## Stripe objects remain in your connected account [#stripe-objects-remain-in-your-connected-account]

If the third-party checkout creates a Payment Intent in the same Stripe account connected to Talivia, use [Payment Intents](https://talivia.com/docs/revenue-guides/stripe/payment-intents). Attach `talivia_session_id` when the third party lets you supply Payment Intent metadata.

If metadata cannot be supplied, identify the signed-in customer with the same email or Stripe Customer ID present on the Stripe payment:

```javascript title="Connect customer identity"
window.talivia.identify('user_123', {
  email: currentUser.email,
  stripeCustomerId: currentUser.stripeCustomerId,
});
```

This links identity; it does not create or confirm revenue in the browser. Stripe's signed webhook remains the source of truth for the payment.

## The processor hides Stripe payment objects [#the-processor-hides-stripe-payment-objects]

Use the [Manual Payment API](https://talivia.com/docs/revenue-guides/manual) after your backend confirms the payment. Send the Talivia session stored with the order and a stable transaction ID.

```javascript title="Record a third-party confirmed payment"
await fetch('https://talivia.com/api/payments/manual', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'x-talivia-api-key': process.env.TALIVIA_API_KEY,
  },
  body: JSON.stringify({
    websiteId: 'YOUR_WEBSITE_ID',
    providerName: 'your-billing-provider',
    transactionId: payment.id,
    providerCustomerId: payment.customerId,
    email: payment.customerEmail,
    amount: payment.amount,
    currency: payment.currency,
    sessionId: order.taliviaSessionId,
  }),
});
```

## Why there is no browser payment command [#why-there-is-no-browser-payment-command]

A public `payment` event can be replayed or fabricated. Talivia therefore separates the two responsibilities:

* browser tracking and `identify` provide attribution context;
* a signed Stripe webhook or authenticated backend API confirms revenue.

This keeps amounts and payment status trustworthy while still supporting custom billing flows.


---

# Stripe Payment Intents (https://talivia.com/docs/revenue-guides/stripe/payment-intents)



Use this guide when your backend calls `stripe.paymentIntents.create` directly. For most new web integrations, Stripe recommends Checkout Sessions with the Payment Element because it manages more checkout behavior for you.

## Carry the session into payment creation [#carry-the-session-into-payment-creation]

Send the Talivia session ID to the backend that owns the Payment Intent. Never create Payment Intents with a secret Stripe key in browser code.

```javascript title="Browser handoff"
const sessionId = window.talivia.getSessionId();

const response = await fetch('/api/create-payment-intent', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ sessionId }),
});

const { clientSecret } = await response.json();
```

Create the Payment Intent on your server and attach the session directly to its metadata.

```javascript title="Create a Payment Intent"
const paymentIntent = await stripe.paymentIntents.create({
  amount: 2500,
  currency: 'usd',
  automatic_payment_methods: { enabled: true },
  customer: stripeCustomerId,
  receipt_email: customerEmail,
  metadata: {
    talivia_session_id: sessionId,
  },
});

return Response.json({ clientSecret: paymentIntent.client_secret });
```

Talivia listens for `payment_intent.succeeded`, records `amount_received`, and deduplicates direct payments by Payment Intent ID. Payment Intents associated with Stripe invoices are left to invoice events so renewal and subscription context is not lost. Checkout-backed Payment Intents whose order reference begins with `cs_` are left to the Checkout Session event so the same payment is not recorded twice.

## Mobile and web-to-app checkout [#mobile-and-web-to-app-checkout]

Pass the original web session ID through your authenticated checkout handoff or deep-link state and store it with the order on your backend. The mobile app does not need the Talivia browser tracker; the backend only needs to attach the previously captured opaque ID when it creates the Payment Intent.

## Identity fallback [#identity-fallback]

Supplying a stable Stripe Customer and receipt email improves matching for later payments. After login or signup on the tracked website, connect that identity:

```javascript title="Identify the Stripe customer"
window.talivia.identify('user_123', {
  email: 'buyer@example.com',
  stripeCustomerId: 'cus_123',
});
```

Identity is a fallback and renewal bridge. Metadata remains the strongest signal for attributing the first payment to the exact checkout session.


---

# Stripe Payment Links (https://talivia.com/docs/revenue-guides/stripe/payment-links)



Payment Links need no custom checkout endpoint. Talivia supports a direct link signal and a return-URL fallback.

## Direct attribution from the link [#direct-attribution-from-the-link]

When the Talivia tracker sees a standard `https://buy.stripe.com/...` anchor, it adds the current session as Stripe's `client_reference_id` before navigation.

```html title="Standard Stripe Payment Link"
<a href="https://buy.stripe.com/test_123">Buy now</a>
```

Stripe includes that reference on the resulting Checkout Session, and Talivia uses it when the payment webhook arrives.

Talivia never overwrites an existing `client_reference_id`. If your product already uses that parameter for a cart or customer ID, configure the return URL below as the attribution signal.

Automatic decoration has boundaries. It applies to normal links on `buy.stripe.com`. A custom Stripe domain or navigation performed directly with `window.location` should use the return URL or your own Checkout Session integration.

## Configure the return URL [#configure-the-return-url]

1. Open the Payment Link in the Stripe Dashboard.
2. Open **After payment**.
3. Choose **Redirect customers to your website**.
4. Set the URL to include Stripe's literal placeholder:

```text title="Payment Link redirect"
https://your-site.com/thanks?session_id={CHECKOUT_SESSION_ID}
```




Keep the Talivia tracker installed on the destination page. Talivia detects the Checkout Session ID, matches it with the verified Stripe webhook, and recalculates attribution even if the webhook arrived before the browser returned.

The return method works best when checkout and the destination page are opened in the same browser. Direct `client_reference_id` attribution does not depend on the customer returning after payment.


---

# Stripe subscriptions and invoices (https://talivia.com/docs/revenue-guides/stripe/subscriptions-and-invoices)



Recurring revenue has two related attribution problems: matching the original subscription signup and reconnecting later invoice payments to the same customer journey.

## Attribute subscription signup [#attribute-subscription-signup]

When Checkout creates the subscription, set the Talivia session on both the Checkout Session and the downstream Subscription.

```javascript title="Subscription metadata"
const metadata = {
  talivia_session_id: sessionId,
};

await stripe.checkout.sessions.create({
  mode: 'subscription',
  line_items: [{ price: 'price_monthly', quantity: 1 }],
  success_url:
    'https://your-site.com/thanks?session_id={CHECKOUT_SESSION_ID}',
  metadata,
  subscription_data: { metadata },
});
```

Stripe exposes Checkout metadata on Checkout events and subscription metadata on Subscription events. For invoices created by a subscription, Stripe places that metadata under the invoice's subscription details. Talivia reads both the current `parent.subscription_details.metadata` shape and the earlier `subscription_details.metadata` shape.

## Connect the customer identity [#connect-the-customer-identity]

Call `identify` when the customer logs in, signs up, or reaches the authenticated product.

```javascript title="Link a Talivia visitor to Stripe"
window.talivia.identify('user_123', {
  email: currentUser.email,
  stripeCustomerId: currentUser.stripeCustomerId,
});
```

Talivia can then attribute a renewal through the Stripe customer even though the renewal happens without a new browser checkout session.

## Events Talivia maintains [#events-talivia-maintains]

The managed Stripe webhook receives:

* successful and failed invoice payments;
* subscription creation, updates, cancellation, pause, resume, trials, and pending updates;
* successful refunds and refund updates;
* dispute creation, updates, closure, and funds movements.

Initial Checkout and invoice events can arrive in either order. Talivia first reconciles the invoice ID when Checkout omits a Payment Intent, then uses the Payment Intent, Checkout Session, customer, amount, and event time as fallback evidence. A match updates the existing payment instead of counting the signup twice.


---

# Test and troubleshoot Stripe attribution (https://talivia.com/docs/revenue-guides/stripe/testing-and-troubleshooting)



Start with the [shared payment testing setup](https://talivia.com/docs/revenue-guides/testing-payment-providers), then test the actual Stripe checkout path used by your product rather than sending only a generic webhook fixture.

## Minimum test matrix [#minimum-test-matrix]

| Scenario                       | Expected Talivia result                                         |
| ------------------------------ | --------------------------------------------------------------- |
| One-time Checkout Session      | One paid payment matched to the checkout session                |
| Direct Payment Intent          | One payment keyed by the `pi_...` ID                            |
| Payment Link                   | Payment matched through `client_reference_id` or the return URL |
| Delayed payment method         | No revenue before asynchronous success                          |
| Subscription signup            | One initial payment plus an active subscription                 |
| Subscription renewal           | One renewal connected to the original customer                  |
| Failed invoice                 | Subscription lifecycle changes without paid revenue             |
| Full or partial refund         | Original payment remains visible and net revenue is reduced     |
| Dispute                        | Dispute state is connected to the original payment              |
| Repeated or out-of-order event | No duplicate payment                                            |

## The connection succeeds but no payment appears [#the-connection-succeeds-but-no-payment-appears]

Check the Stripe Dashboard webhook delivery for the website endpoint. The relevant successful event must be one of:

* `checkout.session.completed` or `checkout.session.async_payment_succeeded`;
* `payment_intent.succeeded` for a direct Payment Intent;
* `invoice.paid` or `invoice.payment_succeeded` for an invoice.

Confirm the event belongs to the same test or live mode as the restricted key connected in Talivia.

## The payment appears but is unattributed [#the-payment-appears-but-is-unattributed]

Inspect the Stripe object used by your flow:

* Checkout Session: `metadata.talivia_session_id`;
* direct Payment Intent: `metadata.talivia_session_id`;
* Subscription: `metadata.talivia_session_id`;
* Payment Link Checkout Session: Talivia-like `client_reference_id` beginning with `s_`;
* return page: `?session_id=cs_...` and a working Talivia tracker.

If metadata is absent, confirm `window.talivia.getSessionId()` returned a value before your backend created checkout.

## Payment Link is not decorated [#payment-link-is-not-decorated]

Automatic decoration requires a normal anchor whose hostname is `buy.stripe.com`. Talivia preserves an existing `client_reference_id`. For custom domains, programmatic navigation, or an existing merchant reference, configure the tracked return URL with `{CHECKOUT_SESSION_ID}`.

## A renewal is unattributed [#a-renewal-is-unattributed]

Confirm the first subscription payment was attributed and that later invoices use the same Stripe Customer. Add `subscription_data.metadata` during signup and call `window.talivia.identify` with the Stripe Customer ID after authentication.

## A refund is not applied [#a-refund-is-not-applied]

Confirm that Talivia imported the original payment and that the successful refund references the same Stripe Payment Intent or Charge ID. When a successful refund cannot be matched, Talivia returns an error without marking the webhook event as processed so Stripe can retry after the original payment is available.

## Reconnect Stripe [#reconnect-stripe]

Pasting an updated restricted key makes Talivia reconcile the existing Stripe webhook URL and event list instead of creating a duplicate endpoint. If the original connection predates managed endpoint IDs, the first update creates and stores a new managed endpoint.


---

# Testing payment integrations (https://talivia.com/docs/revenue-guides/testing-payment-providers)



Talivia does not have a **Live / Test** switch. The credential connected to a website determines which provider environment Talivia calls and where it provisions the managed webhook.

Keep the data separate. Use one Talivia website for staging or sandbox payments and another for production. This keeps test revenue out of production conversion and attribution reports.

## Use two websites [#use-two-websites]

| Talivia website   | Tracked experience            | Provider credential          | Data it should contain      |
| ----------------- | ----------------------------- | ---------------------------- | --------------------------- |
| Product – Sandbox | Staging site or test checkout | Test or sandbox key/token    | Test payments only          |
| Product           | Production site and checkout  | Live or production key/token | Real customer payments only |

The provider environment is only a connection detail. Talivia verifies and processes every supported event delivered by that connection; it does not classify, hide, or filter revenue by a separate payment mode.

## Shared test flow [#shared-test-flow]

1. Create the sandbox Talivia website and install the tracker on the staging experience.
2. Connect the provider's test credential in **Website settings → Revenue**.
3. Complete checkout from a tracked browser session.
4. Confirm the payment amount, currency, status, and provider.
5. Confirm the payment is matched to the expected session and traffic source.
6. Follow the provider guide for refunds, subscriptions, delivery logs, and provider-specific errors.

When the flow is verified, connect the live credential to the production Talivia website. Keep the sandbox website for later integration changes.

## Provider-specific checks [#provider-specific-checks]

Stripe

Checkout events, Payment Links, invoices, disputes, and refunds.

Dodo Payments

Environment detection, webhook delivery, checkout metadata, and refunds.

LemonSqueezy

Key mode, webhook events, custom checkout data, and subscriptions.

Polar

Token permissions, sandbox checkout, attribution, and refunds.

Yolfi

Event routing, signatures, metadata, and subscription updates.

Manual Payment API

Stable transaction IDs, session matching, and safe retries.


---

# Yolfi (https://talivia.com/docs/revenue-guides/yolfi)



Connect your Yolfi organization once to start receiving revenue in Talivia.

## Connect Yolfi [#connect-yolfi]

1. In the Talivia dashboard, select your website and open **Settings**.




2. Select **Payments** and choose **Yolfi**. Then [create an API key in Yolfi](https://app.yolfi.com/settings/api-keys),
   paste it into Talivia, and click **Connect Yolfi**.




## Match payments to sessions [#match-payments-to-sessions]

Choose how customers open Yolfi checkout. Both options use the Checkout Session ID from the
return URL; you do not need to send Talivia metadata.

Payment Links

Match payments from links created in the Yolfi dashboard.

Checkout Session API

Match payments from Checkout Sessions created by your backend.

Having trouble? [Test your Yolfi integration](https://talivia.com/docs/revenue-guides/yolfi/testing-and-troubleshooting).


---

# Yolfi Checkout Session API (https://talivia.com/docs/revenue-guides/yolfi/checkout-session)



Complete the [Yolfi connection setup](https://talivia.com/docs/revenue-guides/yolfi#connect-yolfi) before
continuing.

Use this guide only when your backend creates a Checkout Session. If you created a reusable link
in the Yolfi dashboard, follow the [Payment Links guide](https://talivia.com/docs/revenue-guides/yolfi/payment-link-on-your-site).

## Create the Yolfi Checkout Session [#create-the-yolfi-checkout-session]

Keep your Yolfi API key on the backend. Set `successUrl` with the literal
`{CHECKOUT_SESSION_ID}` placeholder:

```javascript title="Create a Yolfi Checkout Session"
const checkout = await fetch('https://app.yolfi.com/api/checkout-sessions', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.YOLFI_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    paylinkId: process.env.YOLFI_PAYLINK_ID,
    successUrl: 'https://your-site.com/thanks?session_id={CHECKOUT_SESSION_ID}',
  }),
}).then(response => response.json());

return Response.json({ url: checkout.data.url });
```

Send the customer to `checkout.data.url`. After payment, Talivia reads `session_id` from the
return page and matches the payment automatically. No Talivia metadata is required.

For subscriptions, use the same `successUrl` for the first checkout. Renewals are connected to
the original payment automatically.

See [Yolfi Checkout Sessions](https://docs.yolfi.com/en/paylinks/checkout-sessions) for the full
request and response schema.


---

# Attribute revenue with Yolfi Payment Links (https://talivia.com/docs/revenue-guides/yolfi/payment-link-on-your-site)



Complete the [Yolfi connection setup](https://talivia.com/docs/revenue-guides/yolfi#connect-yolfi) before
continuing.

In Yolfi, open your Payment Link and go to **After Completion**.

For **Action After Payment**, choose **Redirect** and use:

```text
https://your-site.com/thanks?session_id={CHECKOUT_SESSION_ID}
```




That is all you need. Talivia reads `session_id` when the customer returns and matches the
payment automatically. No Talivia metadata is required.

## Shared links and QR codes [#shared-links-and-qr-codes]

The same redirect works when you share the Payment Link in email, chat, social media, or a QR
code. If the customer never returns to a page with the Talivia tracker, the payment is still
recorded but cannot be matched to a web session.

## Subscriptions [#subscriptions]

Use the redirect for the first subscription checkout. Later renewals are connected to the
original payment automatically and do not need another browser redirect.


---

# Test and troubleshoot Yolfi (https://talivia.com/docs/revenue-guides/yolfi/testing-and-troubleshooting)



## Test a payment [#test-a-payment]

1. [Connect Yolfi](https://talivia.com/docs/revenue-guides/yolfi#connect-yolfi).
2. Open checkout from a page with the Talivia tracker installed.
3. Complete a payment and return to your site.
4. Confirm the payment appears in Talivia with the expected traffic source.

## The connection fails [#the-connection-fails]

* Create a new key in [Yolfi API settings](https://app.yolfi.com/settings/api-keys).
* Confirm the key belongs to the organization you want to connect.
* Paste the new key into Talivia and connect again.

## No payment appears [#no-payment-appears]

Confirm that Yolfi is still connected in **Website Settings → Payments**, then complete a new test
payment. You do not need to add a website ID or Talivia metadata to the payment.

## The payment is unattributed [#the-payment-is-unattributed]

Confirm that your success page has the Talivia tracker and that the redirect URL contains:

```text
https://merchant.example/thanks?session_id={CHECKOUT_SESSION_ID}
```

For renewals, the first subscription payment must be matched before later payments can reuse its
attribution.


---

# Subdomain tracking (https://talivia.com/docs/subdomain-tracking)



Use one Talivia website ID and the same root `data-domain` on every subdomain:

```html
<script
  defer
  src="https://talivia.com/script.js"
  data-website-id="YOUR_WEBSITE_ID"
  data-domain="example.com"
></script>
```

This covers flows such as:

```text
example.com -> app.example.com -> checkout.example.com
```

If the website only runs on one hostname, this setup is optional: tracking works with a host-only cookie. Talivia Cloud includes `data-domain` in the generated snippet so a later move to subdomains does not silently split visitor identity.

Talivia stores an anonymous visitor cookie for 365 days and refreshes the shared session cookie for 30 minutes after activity. Tabs and subdomains therefore remain in one journey instead of creating separate visitors.

Use the registrable root domain (`example.com`). Do not set `data-domain="app.example.com"` when the visitor also moves through `example.com`.


---

# Tags (https://talivia.com/docs/tags)



Tags let you mark events coming from a specific script installation or environment.

```html
<script
  defer
  src="https://talivia.com/script.js"
  data-website-id="YOUR_WEBSITE_ID"
  data-tag="marketing-site"
></script>
```

Every event sent by that script includes the tag.

## Common uses [#common-uses]

* Separate marketing and app shells when both use the same website id.
* Mark embedded experiences.
* Compare rollout versions.
* Debug staging traffic without creating a second website.

## Filtering [#filtering]

Tags appear as an event dimension and can be used in filters, breakdowns, and event-level investigation.


---

# Team (https://talivia.com/docs/team)



Team access is managed separately for each website. Shared websites appear directly in the invited user's dashboard, so there is no separate team-switching flow.

## Invite someone [#invite-someone]

Open **Settings -> Team**, enter the email of a registered Talivia user, choose a role, and click **Invite**. The user should sign in with the same email address to see the website.




## Roles [#roles]

* **Viewer** has read-only access to dashboards, reports, and sessions.
* **Member** can also update website settings and integrations.
* **Owner** manages invitations and access, and can delete the website.

## Manage access [#manage-access]

The Team page shows the website owner and every invited user with their current role. The owner can change access or remove a user when it is no longer needed.

Review the list after contractor work, agency handoffs, or other temporary collaboration.


---

# Track events (https://talivia.com/docs/track-events)



Use custom events for actions that matter more than a page view: signups, checkout clicks, demo requests, external links, and activation steps.

## HTML attributes [#html-attributes]

Add `data-talivia-event` to an element:

```html
<button data-talivia-event="signup-click">Start free trial</button>
```

Add event data with `data-talivia-event-*` attributes:

```html
<button
  data-talivia-event="checkout-click"
  data-talivia-event-plan="pro"
  data-talivia-event-location="pricing"
>
  Checkout
</button>
```

Talivia automatically reads these attributes on click.

## Track when an element becomes visible [#track-when-an-element-becomes-visible]

Add `data-talivia-visible` to any element that matters: a pricing section, CTA, banner, alert, or modal.

```html
<section data-talivia-visible="pricing-seen">
  <h2>Simple pricing</h2>
</section>
```

Talivia sends the `pricing-seen` event once per page view when 50% of the element is visible.

Use optional attributes when the default is not right for an element:

```html
<button
  data-talivia-visible="signup-cta-seen"
  data-talivia-visible-threshold="0.7"
  data-talivia-visible-delay="700"
>
  Start free trial
</button>
```

* `data-talivia-visible-threshold` accepts `0.1` through `1`. The default is `0.5`.
* `data-talivia-visible-delay` waits for the element to remain visible before sending the event. The default is `0` milliseconds.

### Visibility event data [#visibility-event-data]

Every visibility event includes these numeric properties:

| Property                | Example | Meaning                                                                                             |
| ----------------------- | ------: | --------------------------------------------------------------------------------------------------- |
| `visibility_percentage` |    `80` | The actual visible portion of the element when the event was sent, expressed from `0` to `100`.     |
| `threshold`             |   `0.7` | The configured visibility ratio required to qualify, expressed from `0.1` to `1`.                   |
| `delay`                 |   `700` | How long the element had to remain continuously visible before the event was sent, in milliseconds. |

For the example above, Talivia sends event data equivalent to:

```json
{
  "visibility_percentage": 80,
  "threshold": 0.7,
  "delay": 700
}
```

`threshold` and `visibility_percentage` use different scales: `0.7` means a 70% threshold, while
an observed value is stored as `70` or higher. `delay` is the required continuous-visible duration,
not a timestamp. These properties work like any other event data in Sessions, Goals, and
[Funnels](https://talivia.com/docs/funnels#filter-an-event-step).

## Links [#links]

For normal links, Talivia waits for the event request before navigating when possible.

```html
<a href="/pricing" data-talivia-event="pricing-link">Pricing</a>
```

External links, modifier-key clicks, and `_blank` links are not blocked.

## JavaScript [#javascript]

```js
window.talivia.track('invite-sent', {
  role: 'viewer',
});
```

Use JavaScript when the event depends on application state, form results, or a server response.

## Event data tips [#event-data-tips]

* Use stable names like `signup-click`, not user-facing button text.
* Keep numeric values as numbers when you want to compare them later.
* Avoid sending personal information unless it is needed for payment attribution and allowed by your privacy policy.


---

# Tracker configuration (https://talivia.com/docs/tracker-configuration)



The tracker reads configuration from `data-*` attributes on the script tag. For a normal Talivia Cloud installation, copy the complete snippet from **Settings -> Tracking** and leave its generated attributes unchanged.

```html
<script
  defer
  src="https://talivia.com/script.js"
  data-website-id="YOUR_WEBSITE_ID"
  data-domain="example.com"
  data-auto-track="true"
></script>
```

Only `data-website-id` is required for tracking one hostname. Talivia Cloud normally generates `data-domain` too, which is safe to keep and allows the same anonymous identity to continue across subdomains.

## Domain attributes [#domain-attributes]

These similarly named attributes solve different problems:

| Attribute                   | Use it for                                                                                                                     |
| --------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `data-domain`               | Set the cookie scope. Use one root such as `example.com` when the same visitor moves between `example.com` and its subdomains. |
| `data-domains`              | Restrict the hostnames where this script is allowed to collect. It does not share identity.                                    |
| `data-cross-domain-domains` | Continue a journey between unrelated roots such as `example.com` and `example.net` with a signed linker.                       |

For a website that only runs on one hostname, no manual domain configuration is required. For subdomains, follow [Subdomain tracking](https://talivia.com/docs/subdomain-tracking). For unrelated roots, use [Cross-domain tracking](https://talivia.com/docs/cross-domain-tracking).

## Available attributes [#available-attributes]

| Attribute                   | Description                                                                                                                               |
| --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `data-website-id`           | Required website id.                                                                                                                      |
| `data-host-url`             | Override the collection endpoint origin for self-hosting or a custom reverse proxy. Do not set it on a normal Talivia Cloud installation. |
| `data-domain`               | Optional cookie domain shared by the website and its subdomains. Talivia Cloud generates it from the configured website domain.           |
| `data-auto-track`           | Set to `false` to disable the first automatic page view.                                                                                  |
| `data-domains`              | Optional comma-separated hostname allowlist. Subdomains do not need to be listed for shared identity.                                     |
| `data-cross-domain-domains` | Comma-separated root domains allowed to receive a signed Talivia linker.                                                                  |
| `data-do-not-track`         | Set to `true` to respect browser Do Not Track.                                                                                            |
| `data-exclude-search`       | Set to `true` to remove query strings before sending URLs.                                                                                |
| `data-exclude-hash`         | Set to `true` to remove hash fragments before sending URLs.                                                                               |
| `data-tag`                  | Attach a tag to every event from this script.                                                                                             |
| `data-before-send`          | Name of a global function that can edit or cancel payloads.                                                                               |
| `data-fetch-credentials`    | Fetch credentials mode. Defaults to `omit`.                                                                                               |
| `data-performance`          | Set to `true` to collect Web Vitals.                                                                                                      |

## beforeSend [#beforesend]

```html
<script>
  window.taliviaBeforeSend = (type, payload) => {
    if (payload.url?.includes('/internal-preview')) return null;

    return payload;
  };
</script>

<script
  defer
  src="https://talivia.com/script.js"
  data-website-id="YOUR_WEBSITE_ID"
  data-before-send="taliviaBeforeSend"
></script>
```

Return `null` or `undefined` to cancel the event.

## Domain allowlist [#domain-allowlist]

This is an optional restriction, not a requirement for subdomain tracking.

```html
<script
  defer
  src="https://talivia.com/script.js"
  data-website-id="YOUR_WEBSITE_ID"
  data-domains="example.com"
></script>
```

One root entry covers that domain and its subdomains. This is useful when the same layout can render on staging, preview, and production domains.

## Collection host [#collection-host]

The script automatically sends data to Talivia Cloud. `data-host-url` exists for self-hosted installations and custom reverse proxies where the browser must send collection requests to another origin. It is not an additional URL for your tracked website and should be omitted from normal Cloud snippets.

## Identity storage [#identity-storage]

Talivia stores its anonymous visitor and rolling session identifiers in first-party cookies.

## Visitor and session lifetime [#visitor-and-session-lifetime]

* The anonymous visitor cookie lasts for 365 days.
* The session cookie lasts for 30 minutes and refreshes whenever the tracker sends activity.
* Closing a tab does not split an active session. All tabs and configured subdomains reuse the same rolling session.

When multiple subdomains must share identity, use the root registrable domain for `data-domain`, such as `example.com`, not `app.example.com`. Copy the generated snippet from **Settings -> Tracking** and review [Subdomain tracking](https://talivia.com/docs/subdomain-tracking) before changing the value manually.

## Sensitive query parameters [#sensitive-query-parameters]

Talivia removes OAuth credentials, signed cross-domain tokens, and checkout session ids from stored URL queries. Payment return detection still runs before sanitization, so Stripe and other checkout attribution continues to work without displaying secrets in analytics.


---

# Tracker functions (https://talivia.com/docs/tracker-functions)



The tracker exposes a small browser API after the script loads.

## Track a page view [#track-a-page-view]

```js
window.talivia.track();
```

Use this when automatic tracking is disabled or when you need to manually send a page view after a route transition.

## Track a custom event [#track-a-custom-event]

```js
window.talivia.track('signup-button');
```

Event names are limited to 50 characters.

## Track an event with data [#track-an-event-with-data]

```js
window.talivia.track('signup-button', {
  plan: 'pro',
  location: 'pricing',
});
```

Event data can include strings, numbers, arrays, and nested objects. Keep payloads small: Talivia truncates long strings and limits object shape so reports stay fast.

## Override page properties [#override-page-properties]

```js
window.talivia.track({
  website: 'YOUR_WEBSITE_ID',
  url: '/pricing',
  title: 'Pricing',
});
```

## Use a function [#use-a-function]

```js
window.talivia.track(props => ({
  ...props,
  url: '/checkout',
  title: 'Checkout',
}));
```

The function receives the current tracker payload and returns the payload to send.

## Identify a visitor [#identify-a-visitor]

```js
window.talivia.identify('user_123', {
  email: 'founder@example.com',
  stripeCustomerId: 'cus_123',
});
```

Use identify after login or signup. Talivia stores session data and can connect a payment provider customer to the visitor.

## Read checkout context [#read-checkout-context]

```js
const sessionId = window.talivia.getSessionId();

await fetch('/api/create-checkout', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ sessionId }),
});
```

`getSessionId()` returns the opaque value stored in the `talivia_session_id` first-party cookie. Send only this value to your backend and attach it as `talivia_session_id` provider metadata. It is an attribution identifier, not an authentication credential.


---

# Tracking overview (https://talivia.com/docs/tracking)



Talivia's browser tracker records page views automatically and exposes a small JavaScript API for custom events, identity, and checkout attribution.

## Script [#script]

```html
<script
  defer
  src="https://talivia.com/script.js"
  data-website-id="YOUR_WEBSITE_ID"
  data-domain="example.com"
></script>
```

The script reads browser context, watches client-side route changes, and sends page views. By default, Talivia keeps an anonymous visitor cookie for one year and a rolling 30-minute session cookie.

A single hostname works without `data-domain`. Talivia Cloud includes it in the generated snippet so `example.com`, `app.example.com`, and other subdomains can share the same visitor and session when needed. Keep the complete snippet from **Settings -> Tracking** instead of rebuilding it from this example.

Use [Tracker configuration](https://talivia.com/docs/tracker-configuration) for optional script settings and [Subdomain tracking](https://talivia.com/docs/subdomain-tracking) for a complete shared-cookie setup.

## Runtime API [#runtime-api]

When the script loads, it creates `window.talivia`:

```js
window.talivia.track();
window.talivia.track('signup-click');
window.talivia.identify('user_123', { email: 'founder@example.com' });
window.talivia.getSessionId();
```

## Collection endpoint [#collection-endpoint]

The tracker sends data to Talivia's collection endpoint and receives signed cache and cross-domain tokens. Tokens are short-lived and contain anonymous tracking keys, not account or payment credentials.

## Revenue context [#revenue-context]

For checkout flows, follow the connected provider's revenue guide. Stripe and Yolfi use a unique
Checkout Session ID on the browser return. Providers without that return signal can use
`window.talivia.getSessionId()` in their supported checkout metadata.


---

# Getting updates (https://talivia.com/docs/updates)



Talivia Cloud updates automatically. You do not need to upgrade the tracker script manually when the hosted app ships new features.

## Tracker updates [#tracker-updates]

The script is loaded from Talivia with `defer`, so visitors receive the latest compatible tracker when their browser requests `script.js`.

If your site uses a strict Content Security Policy, make sure the Talivia script origin and collection endpoint are allowed.

## Product updates [#product-updates]

New dashboard features can appear without a site change. For example, revenue attribution, search keyword reports, and session replay use the data already flowing through the tracker and connected integrations.

## When to change your code [#when-to-change-your-code]

You only need to update your site code when you intentionally enable a new tracking behavior, such as:

* Adding custom event attributes.
* Calling `window.talivia.identify`.
* Passing `window.talivia.getSessionId()` into checkout.
* Enabling performance collection with `data-performance="true"`.


---

# Campaign links and UTM (https://talivia.com/docs/utm)



Add tracking parameters to links you share. The **Campaign** tab on the website dashboard groups visitors by the complete set of recognized parameters on each link. For example, `?ref=partner` and `?utm_source=newsletter&utm_medium=email&utm_campaign=launch` appear as separate rows. The expanded Campaign report also shows attributed revenue for each tagged link.

Talivia recognizes `ref`, `via`, `source`, and these standard UTM parameters:

* `utm_source`: who sent the visitor, such as `google` or `newsletter`.
* `utm_medium`: how the link was distributed, such as `cpc`, `email`, or `banner`.
* `utm_campaign`: the promotion or launch name, such as `spring_launch`.
* `utm_content`: which version of a link or ad was clicked, such as `hero_button` or `footer_button`.
* `utm_term`: the paid search keyword or other term used to distinguish search ads.

Use `ref`, `via`, or `source` for a simple tagged link, such as `?ref=partner`. The dashboard Campaign tab shows these alongside UTM tags, with parameter names in gray and values in the main text color. In the expanded report, **Link tags** contains separate `ref`, `via`, and `source` views; **UTM** contains the combined Campaign view and the five individual UTM fields. The individual parameter views show page views.

**Referrer** is the site reported by the browser. **Channel** is a category Talivia infers from the referrer and available tracking tags. Neither is the same as `utm_source` or `utm_medium`. A `ref` or `via` link tag appears in Campaign; it does not change the browser referrer.

Talivia also records common ad click IDs such as `gclid`, `fbclid`, `msclkid`, `ttclid`, `li_fat_id`, and `twclid`. These are not included in Campaign labels.

## Campaign workflow [#campaign-workflow]

1. Add UTM parameters to campaign links.
2. Send traffic to a tracked page.
3. Review the Campaign tab for tagged links, or open the expanded report for each parameter.
4. Connect revenue to see which campaigns produce paid sessions.

## Query cleanup [#query-cleanup]

Use **Settings -> Attribution -> Ignored query params** to remove noisy parameters from stored page queries.


---

# Visitors (https://talivia.com/docs/visitors)



The Visitors report groups multiple visits that Talivia can associate with the same visitor into one profile. Instead of treating every session as a separate person, the report combines visits, page views, custom events, acquisition context, tracker parameters, and attributed payments into one journey.

## Visitor list [#visitor-list]

Open **Visitors** from a website to see recent visitor profiles. Each row includes the visitor label, visit and event totals, acquisition source, attributed spend, and recent activity. Search filters the visitor list, and the full report provides paging through older profiles.




**Acquisition source** is the earliest known source for the visitor. When the most recent visit came from a different source, Talivia shows that latest session source beneath it. This keeps the original acquisition context visible without hiding how the visitor returned.

Open the full Visitors report. Select the expand icon in the upper-right corner of
the Visitors panel. Select any visitor to inspect the complete profile.

## Visitor profile [#visitor-profile]

The profile starts with totals for visits, views, events, attributed spend, and average visit duration. It can also show:

* The visitor ID or a legacy session ID when no visitor record is available.
* A Distinct ID created with [`identify`](https://talivia.com/docs/distinct-ids).
* Linked payment customers and providers.
* First seen, last seen, acquisition source, and latest session source.
* Browser, operating system, device, screen, country, region, and city from the latest visit.
* A long-term activity heatmap.

## Journey activity [#journey-activity]

The **Activity** tab combines the visitor's associated visits into one timeline. Talivia adds an arrival marker for each visit so that the entry host, referrer, landing page, and recognized campaign parameters remain visible alongside page views, custom events, and attributed payments.

The **Properties** tab shows the latest known value for each collected property across the visitor's associated visits.

## Sessions and attribution [#sessions-and-attribution]

Talivia still creates an opaque session ID for each visit. Integrations such as Stripe and the Manual Payment API pass that ID as an attribution signal because it identifies the checkout visit precisely. The interface then presents the matched payment inside the visitor profile and rolls its value into the visitor's spend.

A payment linked to a visitor but not to one specific session can still open the visitor profile. Payments without either match remain visible as unattributed.

## Sorting [#sorting]

Activity can be viewed oldest-first or newest-first. Use oldest-first to follow the journey in the order the visitor experienced it, including each return visit.
