How it works
Four moving parts.
01 · Collection
One script, served from your own subdomain.
You add an A record pointing a subdomain of your site at the tracker host, and one deferred script tag. Because the script comes from your own domain rather than a known analytics host, blockers that work by blocking third-party analytics domains never see it.
Sessions are counted with a rotating server-side hash of connection data. The salt rotates daily, so the same visitor tomorrow is a new session with no way to connect it to today. Nothing is written to the device: no cookie, no localStorage, no sessionStorage. The IP address is used in memory to compute the hash and is never stored.
02 · Attribution
Last non-direct click, session-scoped.
Traffic is attributed on the UTM triple (source, medium, campaign), read from the landing URL at the first event of a session. Later events in the same session are same-site navigations, and their UTMs are ignored so they can’t overwrite the real acquisition source with noise.
A visitor who clicks an ad today and converts next week from a search is credited to the search. Multi-touch attribution needs cross-session identity, and this build has chosen not to have any. That is the honest ceiling without tracking people, and it is where spend decisions actually get made.
Click IDs are never stored. gclid, fbclid and the rest have their values replaced before anything is written, while the parameter name is kept so a paid click is still classified as a paid click.
03 · Spend
Daily, at campaign level, from both platforms.
Every morning the sync pulls campaign spend, impressions and clicks from the Google Ads and Meta APIs. Money and clicks only. Nothing user-level is ever requested from an ad platform, which is what keeps the privacy posture whole rather than merely front-facing.
Each run re-pulls a trailing seven-day window and overwrites, because both platforms restate recent days after the fact. A same-day-only pull would lock in whatever figure happened to be visible the moment the job ran. It also means a missed run heals itself: the next one restates the days the missed one would have written.
Two things that quietly corrupt the numbers
- Timezone. Sessions are stored in UTC; ad platforms report daily spend in the ad account’s own timezone. Joined naively, up to eight hours of every day’s sessions sit against the wrong day’s spend, and the totals still look plausible. You set one reporting timezone per site, each account’s timezone is read from the platform rather than typed, and a mismatch raises a warning instead of being silently reconciled.
- Currency. All ad accounts on a site must share one currency. If they don’t, the sync refuses to run rather than converting at a rate nobody checked. Conversion is a later problem: a wrong rate is worse than a refused sync, because it produces a plausible number nobody questions.
04 · The join

Campaign spend meets sessions on the UTM triple.
A mapping table ties one platform campaign to one UTM triple. Matching campaign names against utm_campaign at query time would need less setup and would break the first time somebody renames a campaign in the ad platform, which happens constantly and silently. A mapping row survives the rename; a string comparison does not.
Because click IDs are dropped, manual tagging carries the attribution. If a campaign ships untagged, its clicks land as direct and its spend sits unmatched. So the product tells you, rather than hiding it in an average:
- Unmatched spend. Money with no session behind it. Tagging is broken, or a campaign is new.
- Unmatched paid sessions. Paid-looking traffic with no spend behind it. A mapping gap, or a typo in a tagging template.
- Unclassified traffic. Source and medium combinations matching no channel rule. Almost always a typo, and invisible everywhere else.
Without that panel the tool reports confidently wrong CPAs, which is worse than no tool at all.
Custom events
One call.
pear.track('signup', { plan: 'pro' })Mark any event you send as a conversion and it becomes the denominator of every CPA in the table. Shopify purchase tracking runs through a checkout-safe custom pixel, documented in full.