Get started
Goals and funnels
Count the visitors who do what matters: reach pricing, start a signup, copy the install script. A goal is one step. A funnel is 2 to 6 steps completed in order on the same day (UTC).
Base URL: https://totallytics.com. Read this page as Markdown.
Create a goal
Open a site, choose the Goals tab and click New goal. A site without goals suggests its top events and pages; pick one to start from it.
Every step matches either:
- Page: pageviews by path.
ismatches exactly,starts withmatches a prefix,containsmatches anywhere in the path. - Event: a custom event by its exact name.
Add filters to narrow a step by page, source, country, device, browser, OS or UTM source, medium and campaign. Filters on different fields must all match. Two filters on the same field match either value. A step takes up to 6 filters and a site up to 20 goals.
Page values start with /, contain no ? or #, and drop trailing slashes, so /pricing/ is saved as /pricing. Event names use letters, digits and _. In a funnel, a page step with no filters matches any pageview.
What the numbers mean
| Number | Meaning |
|---|---|
| Visitors | Unique visitors per day: someone active on 3 days counts 3 times |
| Converted visitors | Visitors with at least one matching pageview or event that day |
| Conversions | Every matching pageview or event |
| Conversion rate | Converted visitors divided by visitors, never above 100% |
| Funnel step | Visitors who completed this step after all earlier steps, in order, on the same UTC day |
| Time to convert | Median and 90th percentile time between two consecutive funnel steps |
The Overview counts visits (entries into the site), so its numbers won't match the visitors on this tab. Dashboard filters apply to goals too: they narrow the pageviews and events that goals are counted over. Funnel bars show each step as a share of step 1, with the drop-off from the step before.
Click a goal to break it down by referrer, entry page, country, device, browser, OS or UTM parameter. Each visitor is counted under the value of their first pageview that day.
Coverage
Goals need a visitor identity on every pageview. The tracking script sends one; older imported data has none. When less than 99% of the pageviews in a range carry an identity, the Goals tab says so:
Goals cover 72% of pageviews in this range (older imported data has no visitor identity).
Changes against the previous period only show when that period is fully covered as well. A range without any identified pageviews shows No visitor data in this range.
Access
All goal routes require the site owner's Firebase ID token, even for public sites. See Authentication.
| Method | Route | Result |
|---|---|---|
| GET | /api/sites/{hostname}/goals |
List goals, oldest first |
| POST | /api/sites/{hostname}/goals |
Create a goal (201) |
| GET | /api/sites/{hostname}/goals/stats |
Numbers for every goal in a date range |
| GET | /api/sites/{hostname}/goals/{id} |
Read one goal |
| PUT | /api/sites/{hostname}/goals/{id} |
Replace a goal |
| DELETE | /api/sites/{hostname}/goals/{id} |
Delete a goal |
| GET | /api/sites/{hostname}/goals/{id}/stats |
Breakdown and funnel timing for one goal |
Goal object
{
"id": "0b7c3e52-6a0e-4f0d-9d51-3f1f5c2a9e10",
"name": "Pricing to signup",
"kind": "funnel",
"steps": [
{
"name": "Pricing",
"match": "pageview",
"filters": [{ "key": "page", "op": "eq", "value": "/pricing" }]
},
{
"name": "Signup completed",
"match": "event",
"filters": [{ "key": "event", "op": "eq", "value": "signup_completed" }]
}
],
"created_at": "2026-09-30T09:12:44.000Z",
"updated_at": "2026-09-30T09:12:44.000Z"
}| Field | Rules |
|---|---|
name |
1 to 80 characters |
kind |
goal (exactly 1 step) or funnel (2 to 6 steps) |
steps[].name |
Optional, up to 40 characters, defaults to Step n |
steps[].match |
pageview or event |
filters[].key |
page, referrer, country, device, browser, os, utm_source, utm_medium, utm_campaign, event |
filters[].op |
eq; prefix and contains only with page |
filters[].value |
Page paths start with /; event names match ^[A-Za-z0-9_]{1,256}$ |
An event step has exactly one event filter with op: "eq"; a pageview step cannot use the event key. A goal step needs at least one filter. Two identical steps in a row, or the same filter twice in a step, are rejected.
A goal that no longer passes validation is listed with "invalid": true and left out of stats until it is saved again.
Create and change goals
curl -X POST https://totallytics.com/api/sites/example.com/goals \
-H "Authorization: Bearer $TT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"Signup completed","kind":"goal","steps":[{"match":"event","filters":[{"key":"event","op":"eq","value":"signup_completed"}]}]}'POST returns the new goal with 201. PUT takes the same body, replaces the whole goal and returns it. DELETE returns {"deleted": "<id>"}.
Goal stats
GET /api/sites/{hostname}/goals/stats?from=1790208000&to=1790812800&tz=Europe/Amsterdam
from and to are unix seconds, tz sets the chart buckets, and f takes the same filters as the statistics API.
{
"granularity": "day",
"visitors": 2016,
"previous_visitors": 1874,
"coverage": {
"pageviews": 5230,
"identified": 5230,
"previous": { "pageviews": 4870, "identified": 4870 }
},
"goals": [
{
"id": "7d2a8c1e-3b4f-4e6a-8c9d-0e1f2a3b4c5d",
"name": "Signup completed",
"kind": "goal",
"conversions": 143,
"converting_visitors": 118,
"rate": 0.0585,
"previous": { "conversions": 126, "converting_visitors": 104, "rate": 0.0555 },
"series": [
{ "t": 1790208000, "conversions": 19 },
{ "t": 1790294400, "conversions": 23 }
]
}
],
"funnels": [
{
"id": "0b7c3e52-6a0e-4f0d-9d51-3f1f5c2a9e10",
"name": "Pricing to signup",
"kind": "funnel",
"steps": [
{ "name": "Pricing", "visitors": 412 },
{ "name": "Signup completed", "visitors": 61 }
],
"previous": [388, 52]
}
],
"invalid": []
}rateis a fraction from 0 to 1, ornullwhen the range has no visitors.serieshas one entry per hour for ranges up to 4 days, otherwise one per day, zero-filled. Funnels have no series.previous_visitorsand everypreviousarenullwhen the previous period is less than 99% covered.
Goal breakdown
GET /api/sites/{hostname}/goals/{id}/stats?from=1790208000&to=1790812800&dim=referrers&limit=10
dim is one of referrers, pages (entry page), countries, devices, browsers, os, utm_sources, utm_mediums or utm_campaigns. limit is 1 to 100, default 10.
{
"dim": "referrers",
"breakdown": [
{ "name": "google.com", "visitors": 880, "steps": [170, 46] },
{ "name": "Direct / none", "visitors": 640, "steps": [131, 22] }
],
"timing": [{ "p50_s": 204, "p90_s": 3310, "n": 61 }]
}steps has one count per step. timing has one entry per step transition, in seconds, and is null for goals.
Errors
| Status | Error |
|---|---|
| 400 | invalid json, invalid range, invalid filter, unknown dimension or the validation message |
| 401 | sign in required |
| 403 | Install your tracking script to verify this site first |
| 404 | unknown site, unknown goal |
| 429 | too many goals for this site |
| 504 | date range too large for goals, narrow it |