Documentation
Coming from another tool
Reading the reports
Count what matters
Machine access
Numbers that leave the panel.
A read-only page for somebody without an account, tagged campaign links and tracking links that count clicks, one download per screen in six formats, and the digests and alerts that arrive by mail.
Share a live page, not a screenshot
A share link is a read-only page of one site's numbers for somebody who will never have a seat: a client, an investor, a colleague at another company. The alternative people actually use is a screenshot, which is stale the moment it is taken and cannot be revoked. It is built under Tools, Shared links.
- You decide what it shows. The builder offers blocks the reports already answer, over one of eight windows decided when the link is made: today, yesterday, the last 7, 30, or 90 days, month to date, last month, or the last 12 months, cut at your site's own midnights. Every block counts visitor days except Top pages, which counts pageviews the way the Overview box does.
- It works for anyone holding the address. Said plainly, because that is what makes it sendable. The token is 32 random bytes, the page refuses indexing, and it can read its chosen blocks and nothing else.
- An opening counter shows use. The panel lists each link with its recorded opening count and last use. Revoking is immediate, and the row stays so you can review its earlier use.
Shared reports identify counted data and imported history for each period and table. Imported history keeps its source limitations; Kehai cannot apply current exclusion rules to those past aggregates.
The page is drawn with the panel's own cards at the panel's own width: what you send is the product, not a printout of it.
Campaign links
Choose Tagged link for a complete address, or Google Ads ValueTrack for a final URL suffix. The Google Ads preset fills campaign, keyword and ad content placeholders, and keeps them readable while encoding static text safely. Copy the suffix into Google Ads URL options, without a leading question mark or {lpurl}, and keep the landing page in Final URL. Google expands the placeholders when an ad is clicked; use its URL test before publishing. A suffix is copied directly to Google Ads, rather than saved as a shortened redirect.
A builder under Tools that composes a tagged address, so the visits a campaign brings arrive under a name somebody chose rather than as direct traffic. It offers exactly the five fields the collector reads off a landing address, utm_source, utm_medium, utm_campaign, utm_term, and utm_content, and no sixth, because a made-up parameter would be dropped without anybody being told. The same five carry order attribution in ecommerce.
The destination is a path on your own domain, because an address Kehai does not measure produces no visit to attribute. A path that already carries a query keeps it, and the campaign joins it with &. A path with a fragment before its query, like /faq#shipping, is refused with a sentence: a fragment never reaches a server, and moving the query in front of it would change what you typed. Two warnings appear when they apply, because they are the two ways campaign tagging actually fails and neither is a syntax error: capitals, since Facebook and facebook become two rows, and a value that names a person, since a campaign value is stored as written and shown in a report.
Tracking links, and the history of every address
A tagged address answers what a campaign produced once somebody landed. It cannot say how many people clicked, because a message opened and closed leaves nothing behind. Generate tracking link turns the address you just built into stats.kehai.io/k/{slug} on the same row: a short address that counts the click and then sends the reader on to the destination, campaign parameters and all, so one link does both jobs.
- Scanners are counted apart, not dropped. Mail gateways and safe-link services open every link in every message. Their clicks are kept and shown as "by scanners" beside the human count, because dropping them silently would be as wrong as counting them.
- A click is not a visit. A reader can click and close, or be a scanner, and never arrive. If they do arrive, the snippet counts the visit as it counts any other, under the campaign the address carried.
- The count is the link's whole life, bounded only by the site's retention, never a trailing window.
- The reader is always sent on, whether or not the click was recorded. Somebody who clicked a link in an email is owed the page.
Every address you save is kept under "Links you have built", newest first, twenty to a page, with an optional note, which is the part that matters in six months: a campaign name does not say which of four sends it was. Forgetting a plain tagged address deletes it. Forgetting a tracking link revokes it instead, so the address stops redirecting and its recorded clicks remain available. An address already inside a mailing stops working when you revoke it. Clear history does both at once.
Exports, from one screen to everything
| Export | What leaves |
|---|---|
| one screen | One download from the menu in the screen's header, and nowhere else: every dataset on the screen at once, one per card, as CSV, JSON, NDJSON, Markdown, or XML, or Copy for AI, the same rows prefixed with the site, the range, the filters, and a one-sentence definition of the metric, shaped to be pasted to an assistant. A card that is loading, empty, or prose stays out |
| site archive | Site settings and retained analytics datasets in one NDJSON file from Settings, Your data. Export is available on every plan. Import restores supported datasets and settings into an existing site within its retention and access rules |
| raw rows | Newline-delimited JSON for the supported retained analytics datasets over the API, including fields that aggregate reports do not display |
| Google Ads conversions | Eligible positive commerce sales from Tools, as a Google Ads CSV or authenticated HTTPS feed. Requires the actual sale time and the order's raw GCLID; refunds are not conversion adjustments |
Archive import restores retained datasets and site settings, including funnels, goal mappings, campaign links, and shared report configurations. Account memberships and credentials stay with the account. The destination keeps its domains, public identifier, and retention setting. Public link configurations arrive revoked, and blocking rules arrive inactive. If an import stops or its response is lost, choose the exact same file again to resume safely. A completed file shows its earlier result without making changes. Different or edited archives are separate imports and may overlap existing data. See archive import for retention and reset behavior.
A screen's file describes the card, not the rows in view: a paginated ranking exports every row the answer holds, and a chart exports every plotted bucket, zeros included. Column names say what the screen says, so a column of visitor days is headed "Visitor days".
Digests: on schedule, by mail
Under Settings, Notifications, each person switches on their own weekly or monthly digest per site. Nothing is mailed to somebody who did not ask. A digest arrives whether or not anything happened, which is what makes it different from an alert: it carries the period that just closed and the one before it, and nothing else. It is sent for the period once the period has finished rather than on a fixed day, so a restart never sends it twice and a failed morning never skips it. A period's last day is judged only once it is settled, meaning it holds at least one measured row or has been closed for six hours in the site's own zone, so a digest waits a pass rather than closing a month a day short. Every message links back to the exact report and period it describes, and carries an unsubscribe link that works without signing in.
Alerts: when a day breaks the pattern
An alert, under Settings, Alerts, watches one number on one slice of the site and says something when a day breaks the pattern that number has been holding. It is not a threshold: a blog swinging between eight and eighty visitors and a shop that sits within five percent of its trend both need to be told when their own shape breaks, and one percentage cannot mean the right thing on both.
| Field | What it decides |
|---|---|
| Watching | Visitor days, visits, pageviews, a goal's completions, or a goal's revenue |
| Revenue currency | Choose one currency for a revenue alert. Create separate alerts to watch several currencies. Automatic works only when the history being evaluated has one revenue currency; when several are present, the alert waits for a selection |
| Slice | Up to four filters, each narrowing what is counted exactly as it narrows a report. Empty watches the whole site |
| Benchmark | How many previous days each day is compared with. The model still uses all available history |
| Tell me about | Falls only, rises only, or both |
| Email me | Your own switch. An alert reaches the bell of everybody with the site the moment it fires, and reaches by mail exactly the people who switched this on, whatever their role |
A day qualifies when it lands outside the range the site's own history predicts and no day inside the benchmark broke the same way as hard. A day lower than any in that window always qualifies, whatever the arithmetic says, because that is what a removed snippet looks like. At most one message per alert per week, so a run of strange days is one message rather than four. A young site stays quiet until it has enough history to know its own shape, because turning a new site's first ordinary traffic into a fabricated emergency helps nobody. A day is judged only once it is settled, the same rule the digests follow, so an outage and a day not yet written are never confused. Every alert links to the exact report, slice, and day it fired on, including the measured currency for revenue. A spike mail says so itself: it is a heads up, not a warning. A drop mail names the first thing worth checking: a missing snippet, a failed deploy, and a genuinely quiet day all look the same from the outside.