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. is matches exactly, starts with matches a prefix, contains matches 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

json
{
  "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

bash
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.

json
{
  "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": []
}
  • rate is a fraction from 0 to 1, or null when the range has no visitors.
  • series has one entry per hour for ranges up to 4 days, otherwise one per day, zero-filled. Funnels have no series.
  • previous_visitors and every previous are null when 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.

json
{
  "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