Profit per channel is the net revenue attributed to an acquisition channel, after processor fees and refunds, minus what you spent on that channel in the same period. This post explains every step ProductLense takes to compute it, and where its limits are. The short reference version is in the methodology docs.

Step 1: record the first touch

Every visitor’s first event stores where they came from: the channel, utm_source, utm_medium, utm_campaign, the referrer domain, the landing page and the time. Channels are classified on arrival: click ids or paid mediums (cpc, ppc, paid, paidsocial, display) are paid, utm_medium=email is email, and the referrer decides between AI assistant, social, organic search, referral and direct.

Because ProductLense is cookieless, an anonymous visitor is one browser on one day. That sounds limiting, but for revenue it rarely matters, because of step 2.

When someone signs up or logs in, your code calls:

js
window.productlense('identify', 'user_123', { email: '[email protected]' });

From that moment, the visitor is linked to user_123. Every later visit, on any day, joins the same person, and the first touch stays the one recorded before signup.

Payments arrive from your billing provider by webhook, by a 12-month backfill when you connect, by a nightly reconcile, or through the payments API. Each one is resolved when it is written:

  1. the user id in the provider’s customer metadata (pl_user_id), matched to an identify call;
  2. otherwise the customer email, matched to the email you sent in identify traits;
  3. otherwise a ProductLense visitor id placed in metadata.

The chain is payment → customer → identity → visitor → first touch, and the resolved channel, source, campaign and landing page are stored on the payment row. Resolving at write time means every revenue report is a plain query over one table. Payments that cannot be matched yet are retried nightly, so an identify call that arrives after the payment still credits the right channel.

Step 4: compute net revenue

Gross charges overstate what you keep. For every payment ProductLense stores the amount, the currency, and the fee the provider reports:

text
charge:                 net = amount − fee
refund or chargeback:   net = −(amount + fee)

Refunds subtract the fee too, because most processors keep the original fee when you refund. For merchants of record, the fee is what they keep, including the tax they remit: Paddle’s fee is grand total minus earnings, so net revenue equals your payout. Every amount is converted to USD at the European Central Bank reference rate for its day and also kept in its original currency.

Step 5: subtract ad spend

Ad spend comes from manual entries or a CSV with date, channel, source, medium, campaign, amount, currency. It joins to revenue on channel, source, medium and campaign, the same keys the first touch carries from your UTM tags.

text
profit(channel, period) = Σ net revenue of payments attributed to channel and paid in period
                          − Σ ad spend for channel in period

Then three ratios:

text
CAC     = ad spend / new customers
ROAS    = attributed net revenue / ad spend
payback = CAC / average net revenue per new customer in their first 30 days

A worked example

An example month for one channel, Google Ads, with round numbers:

ItemAmount
Gross revenue from customers whose first touch was Google Ads$1,200
Processor fees on those payments$40
Refunds$100
Net revenue$1,060
Google Ads spend$500
Profit$560
New customers10
CAC$50
ROAS2.12×

If those ten customers paid $53 net on average in their first 30 days, payback is $50 / $53 ≈ 0.9 months: the channel earns back what each customer cost within the first month.

The same table for a channel with $2,000 of spend and the same revenue would show a loss of $940, with a minus sign and a down arrow next to it. That is the row you want to see before next month’s budget, not after.

What this method does not do

  • No multi-touch in v1. First touch gets full credit. Last touch and linear models are planned as a toggle in v1.1, computed by re-resolving the same payments.
  • No view-through attribution. An ad someone saw but did not click leaves no trace on your site, so it gets no credit.
  • Spend is manual or CSV today. Google Ads and Meta Ads spend connectors are planned for v1.1.
  • Identify matters. Without it, ProductLense can only match payments by email or a visitor id in metadata, and anonymous visits on different days stay separate.
  • Refunds land in the period they happen. A refund in November for an October sale reduces November’s net revenue for that channel, which matches your cash, not your bookings.
  • Some providers hide fees. Lemon Squeezy, Chargebee, Shopify orders and Creem do not expose fees through the APIs ProductLense reads, so profit for those connections is before fees.

Why first touch is the default

For small SaaS companies, the expensive question is which channel to put more money or time into, and that is a question about where customers start. Closing channels such as email and retargeting only work on people another channel already brought. First touch is also the model that is easiest to check by hand, which matters when the number decides a budget.

Profit per channel is on the Growth and Scale plans. The methodology page has every formula.

Free up to 10k events a month. No card.

Add the script, connect Stripe or any of 14 other billing providers, and see revenue by channel the same day.