MenuHow ProductLense counts

Get started

How ProductLense counts

The exact definitions behind every number ProductLense shows: visitors, sessions, channels, attribution, revenue, fees, profit, and where counts approximate.

This page defines every number in the dashboard and how it is computed. When a figure is approximate, the page says so and gives the error bound.

Visitors

A visitor is one browser on one site on one UTC day:

Text
visitor_id = first 16 hex characters of sha256(site_id | ip | user_agent | daily_salt)

The salt is 32 random bytes generated for each UTC day. The IP address is used for the hash and the country lookup, then dropped; it is never stored. The same browser on the next day gets a different, unlinkable id, so a person who visits on three days counts as three visitors until your code calls identify. See Cookieless visitor counting for the privacy side.

Sessions and bounce rate

A session is a run of events from one visitor with no gap longer than 30 minutes. Sessions are assigned in memory when events arrive.

Text
bounce rate      = bounced sessions / sessions × 100
average duration = mean of (last event time − first event time) per session

Bounce rate, duration, and entry and exit pages are pre-aggregated per day once a day is complete (90 minutes after UTC midnight). Days not yet rolled up are read live, so totals never miss sessions.

Signups

Signups are the visitors who called identify in the range. With a channel, source, medium, campaign or referrer filter, signups use the visitor's first touch, the same attribution as the channel table.

Channels

Every event is classified when it arrives. The first rule that matches wins:

OrderRuleChannel
1URL has a gclid, fbclid or msclkid valuepaid
2utm_medium is cpc, ppc, paid, paidsocial or displaypaid
3utm_medium is emailemail
4Referrer is an AI assistant: chatgpt.com, chat.openai.com, perplexity.ai, claude.ai, gemini.google.com, copilot.microsoft.com, you.com, poe.com, meta.ai, grok.com, x.ai, mistral.ai (and their subdomains), or DuckDuckGo with ia=chatai_assistant
5Referrer is a social network: twitter.com, x.com, t.co, facebook.com, instagram.com, linkedin.com, reddit.com, youtube.com, tiktok.com, threads.net, bsky.app, news.ycombinator.com, producthunt.com (and subdomains)social
6Referrer domain contains a search engine label: google, bing, duckduckgo, yahoo, baidu, yandex, ecosia, braveorganic_search
7No referrer, but a source (utm_source, or ref, via or source when there is no utm_source) that names an AI assistant, social network or search engine by domain or by name, such as chatgpt.com, producthunt, twitter, hn or googleai_assistant, social or organic_search, by the lists in rules 4 to 6
8No referrer and no source, utm_medium or utm_campaigndirect
9Anything elsereferral

A referrer on your own hostname is treated as no referrer, so internal navigation never becomes referral. Rule 7 matters because browsers and apps often strip the referrer: ChatGPT, for example, adds utm_source=chatgpt.com to its links instead. UTM values for source and medium are lower-cased; campaign, term and content keep their case.

First touch

The first pageview of each visitor fixes its first touch: channel, utm_source, utm_medium, utm_campaign, referrer domain, landing path and country. It is kept for the life of the site, after raw events expire, so a payment months later can still be attributed.

Attribution

ProductLense uses first-touch attribution. When a payment is written, ProductLense looks for the paying customer's visitors in this order and stops at the first source whose visitors have a first touch:

  1. The user id on the customer (from metadata keys pl_user_id, user_id, userId or uid, or the provider's own field, such as Polar's external id) matched to your identify calls.
  2. The customer email, matched to the email trait sent with identify, or to a user id that is that email (case-insensitive).
  3. A ProductLense visitor id in the customer metadata (pl_visitor_id or visitor_id).

When one user has several visitors, the earliest first touch wins. The result is stored on the payment row. Payments that could not be matched are tried again every night for 90 days, so an identify that arrives after the payment still credits the right channel. Details: How payments are attributed.

Money metrics

Every money number in ProductLense uses one definition, the same in the dashboard, the API, Ask and these docs. All amounts are USD at the payment date's ECB rate (original currency stored too). Only payments with status succeeded count. A channel's numbers are attributed by first touch.

NameDefinition
RevenueCharges − refunds − chargebacks, before processor fees.
FeesProcessor and merchant-of-record fees on those charges, minus fees returned on refunds. Estimated for providers that do not report fees (fee_estimated_share says how much).
Net revenueRevenue − Fees.
Ad spendAd spend rows for the range, prorated by day.
ProfitNet revenue − Ad spend, i.e. Revenue − Fees − Ad spend.
CustomersDistinct customers with a first succeeded charge in the range (new customers).
CACAd spend ÷ customers, for the same channel and range. Null when customers = 0.
ROASRevenue ÷ Ad spend. Null when spend = 0.
PaybackCAC ÷ average first-month net revenue per new customer.
MRRSum over active, non-trial subscriptions of the period price normalised to a month and divided by interval_count.
LTVAverage net revenue per customer over the customer's lifetime to date.
ARPUNet revenue in range ÷ customers with a succeeded payment in range.

Where Revenue and Profit appear side by side, the difference is always Fees + Ad spend; where Fees are shown, Net revenue = Revenue − Fees. For example:

Text
$2,407 revenue − $152 fees − $1,518 ad spend = $737 profit

Fees per payment

Every payment keeps its original amount and currency, plus a USD amount converted at the European Central Bank reference rate for its day. When a day has no rate, the nearest earlier day within 10 days is used. The fee is what the processor or merchant of record kept, as reported by the provider. Providers that do not report fees get an estimate you set on the connection (a percentage plus a fixed amount), marked as estimated. Each provider page states which case applies; see Refunds, fees and currencies.

Profit by channel

Ad spend joins revenue on channel, source, medium and campaign, and spend entered for a date range is spread evenly over its days. Rows without spend show no CAC, ROAS or payback. See Profit per channel and CAC, ROAS and payback.

Conversion rate

Text
conversion rate = customers / visitors × 100

Per channel, both sides use the channel of the visitor's first touch.

Where counts are approximate

Unique visitors and sessions are stored as fixed-size HyperLogLog states so that a 12-month range loads as fast as a day. The counts are exact for small sets and approximate for large ones:

ReportTypical error
Site totals (Overview tiles and chart), countries, devices, browsers, operating systemsabout 0.8%
Pages, sources, channels, campaigns, referrers, entry and exit pagesabout 1.6%

Below a few hundred to a few thousand uniques per row the count is exact. Pageviews, events, revenue, fees, spend and profit are always exact sums.

In breakdowns, ProductLense first picks the page of rows by pageviews and then counts unique visitors for those rows. A list ordered by visitors can therefore differ slightly at the cut-off from a list ordered purely by visitors over all keys; within the page, rows are sorted by visitors.

    ↑ ↓ to move, Enter to open