Tracking
Tracking settings reference
Every setting Lessly Tracking exposes, what it defaults to, what changes when you change it — and the public routes your product answers on.
Every setting Lessly Tracking exposes, with its default and what changes when you change it. This page is the table; the pages it links to are the explanation.
There is very little to configure. Most of what Tracking does — page views, form identity, batching, bot filtering, deduplication — has no setting at all.
At a glance
| Setting | Where | Default |
|---|---|---|
| The snippet variant | Install | Loader snippet |
data-link-domains | In the snippet | Absent (no group) |
data-collect | On the script tag | Absent |
data-cookie-domain | On the script tag | Absent |
| Install domains | Install, step 2 | Empty |
| The tracking host | Tracking domain | The shared Lessly edge |
| The linking group | Carried in the snippet | Empty |
| Event name status | Events | Active |
| API keys | API keys | None |
| Conversion feedback | Google Ads → Conversions | Off |
| Report model, window, range, domain | Reports | Last Click, 30 days, last 30 days, all domains |
The snippet
Two forms are shown on the Install page. Changing variant means re-pasting the snippet on your site.
| Variant | What it does | Cost of choosing it |
|---|---|---|
| Loader snippet (default) | Defines window.lt before the script arrives, so early lt(…) calls are queued and recorded | None. This is the right choice |
Minimal variant (behind the advanced toggle) | One <script async> tag. Collects exactly the same things automatically | window.lt does not exist until the script has loaded, so an early call throws a ReferenceError and the event is lost |
Attributes on the script tag
| Attribute | What it does | Default |
|---|---|---|
data-link-domains | The cross-domain linking group, as a comma-separated list of root domains. Written into the snippet for you when a group is configured | Absent — no cross-domain work is done and the code for it is never loaded |
data-collect | Sends events to a different collector address instead of the one derived from the script URL. For local development and testing | Absent — the address is derived from the script URL |
data-cookie-domain | Sets the cookie domain explicitly | Absent — the domain is worked out by probing |
A normal install sets none of them by hand. data-link-domains is the only one that appears in a snippet you copy. Everything else about the script — where events go, which product they belong to, which version runs — comes from the script URL. See Install the tracking script.
Domains
Three separate lists, none of which affects the other two. Register the domains you track explains the difference.
Install domains
The checklist on Install, step 2.
- Default — empty.
- Normalisation — lower-cased and trimmed; a scheme, port, path or trailing dot is dropped.
wwwis not removed, soacme.comandwww.acme.comare two entries. Hostnames, IPv4 addresses and IPv6 literals are accepted. - Window — a domain counts as seen if an event arrived from it in the last 30 days. The page rechecks about every ten seconds.
- What changes — nothing about collection. Events are stored from whatever host runs your script, listed or not. Removing a domain removes it from the checklist only; its events stay, and it reappears under
Also sending events.
The tracking host
On Tracking domain: the host your snippet is served from.
- Default — the shared Lessly edge.
- Setting it — claim a host under one of your product’s domains. It is suggested as
analytics.plus your domain and must be a bare hostname under that domain. Publish the DNS records the page gives you. - Statuses —
Waiting for DNS to publish,Active,Verification failed. Verification is a real fetch of the script over your host; automatic retries stop after 72 hours, andRetryrestarts them at any time. - What changes — the script becomes first-party on your site and the snippet is regenerated to point at the new host. Nothing else behaves differently. Re-copy the snippet after a binding goes active, or pages keep loading from the old host.
- Releasing — the host is given up and the snippet falls back to the shared edge.
The linking group
The list of root domains treated as one site for identity, carried in the snippet as data-link-domains.
- Default — empty. With an empty group, or a group of one, no cross-domain work is done at all.
- Normalisation — lower-cased and trimmed to a bare root domain; adding one that is already there changes nothing.
- What changes — links from one domain in the group to another are decorated with the visitor’s anonymous id, and the receiving page adopts it if it has no visitor of its own and the value is under about two minutes old.
- After every change — copy the snippet again and replace it on every site in the group, including the ones you did not change. The group is baked into the pasted HTML, not fetched at run time.
Consent
There is no consent setting, and that is deliberate. The script reads the decision your own banner recorded and switches itself between full and cookieless mode; there is nothing to turn on and nothing to configure.
The one thing under your control is where you put the snippet: load it unconditionally, behind no consent check, and install your banner’s tag above it. What tracking does with a consent answer describes the three states and exactly what each one collects.
Event names
On the Events page, each name your sites have sent is Active (the default) or Archived. Archiving hides a name from the dashboards; nothing else changes — events keep arriving, counts keep rising, nothing is deleted, and Unarchive brings it back. See Record your own events.
API keys
On the API keys page. There are no permissions to choose: a key is bound to one product and may send any event that product accepts.
| Property | Rule |
|---|---|
| Name | For you; it has no effect on what the key can do |
| Secret | Shown once, at creation. Only a hash is kept |
| Rotate | Issues a new secret and revokes the old one in the same step, with no overlap period |
| Revoke | Permanent; the key stays in the list as revoked |
See Send events from your backend.
Google Ads
The connection itself is a platform step, made once outside Tracking. Inside it there are two things to set, both on the Google Ads page — see Close the loop on Google Ads.
Spend sync. Enrolled by the first successful Sync now on Settings, after which it refreshes once a day on its own. The first sync reaches about 30 days back and each daily refresh re-reads roughly the last 7 days.
Conversion feedback, on Conversions. This is the only configuration in Tracking that changes something outside it, so the defaults are deliberately inert.
| Setting | What it does | Default |
|---|---|---|
| Master switch | Nothing is uploaded until it is on | Off |
| What Google learns from | Fill gaps adds to what your pixel counts; Our data only means Google learns from these conversions alone | Fill gaps |
| Match window | How far back a click may be to be matched to a conversion, and the window re-scanned on each run: 14, 30, 60 or 90 days | 90 days |
| Rules | One tracked event name to one Google conversion action, with a value source: dynamic revenue, dynamic, or a fixed amount | None |
| Enhanced conversions | Also sends the person’s hashed email and phone alongside the click id as extra matching signals | Off |
Turning the master switch on starts a daily upload run; Run now does one pass immediately. Changing a conversion action resets the campaign’s learning phase on Google’s side.
Report controls
The four controls on Reports are settings for the question you are asking, not for how data is collected. Nothing is stored under them and nothing is frozen — every change recomputes over the same history.
| Control | Options | Default |
|---|---|---|
| Attribution model | Last Click, First Click | Last Click |
| Lookback window | 7, 14, 30, 60, 90 days | 30 days |
| Date range | Last 7 days, Last 30 days, Last 90 days, Custom | Last 30 days |
| Domain filter | All domains, or one of your domains | All domains |
They are kept in the address of the page, so a report can be shared as a link, and Google Ads → Reports has model, window and range controls of its own. What each does to the numbers is on Read the attribution reports.
The public routes
Four HTTP routes belong to your product and can be called from outside. Three are open and are what the tracking script uses; the fourth is the events route your backend calls with an API key. Every route lives under your product on the tracking host:
https://<tracking host>/<product id>/tracking/<route><tracking host> is the shared Lessly edge by default, or the host you claimed on Tracking domain. <product id> is your product’s id, and it is what identifies whose data this is. You never assemble this yourself: the Install page shows the finished script URL, and the API keys page shows the finished events endpoint with a button to copy it.
| Route | What it is for | Authentication |
|---|---|---|
GET /script/lt.v1.js | The tracking script itself. The version is in the filename, so a future version ships as a new filename and the snippet you pasted keeps loading the one you pasted | None |
GET /script/lt-xdomain.v1.js | The cross-domain part of the script, fetched by the script itself, and only on products that have a linking group. You never reference it yourself | None |
POST /collect | Where the tracking script sends the events it has gathered. In the browser, use lt(…) instead | None — the product comes from the path |
POST /events | Lifecycle and revenue events from your own backend. The only route you authenticate | Your key in the X-Api-Key header — not Authorization |
The three open routes accept requests from any origin and never use cookies or credentials. The script is served with a ten-minute cache lifetime and then revalidated, which is how fixes reach your visitors without you re-pasting anything.
Request and response schemas, status codes and field-level detail are on the Tracking API reference.
What the routes refuse
| Limit | Applies to | Value |
|---|---|---|
| Edge rate limit | All four routes | 10,000 requests per minute from one IP address |
| Body cap | /collect and /events | 64 KiB |
| Batch cap | /events | 500 events in one request |
| Script request body | /script/* | Bodies above 1 KB are refused |
Nothing a normal install does comes near the rate limit: the script sends one batched request every few seconds per visitor, and a backend should batch its events rather than send them one at a time.
/collect is deliberately forgiving, because a page must never break over analytics. An event that does not fit the expected shape is dropped and the rest of the batch is kept, and a batch that names no recognisable product is accepted and discarded. An accepted response therefore means “received”, not “all of it was stored” — Record your own events lists what is dropped after that point.
/events is the opposite: it accounts for every event you send. A batch can be partly accepted, and a success carrying a non-empty rejected list is the normal way to learn that one line was wrong while the others are already stored. A key that does not match the product in the URL is refused, which is what stops a staging key writing into production.
Next steps
- Install the tracking script: what each snippet variant and attribute actually does.
- Register the domains you track: the three domain lists, in full.
- Send revenue from your backend: the fields the events route accepts.
- Browse the Tracking API: the generated schema for every route above.