Skip to main content

Goals

Goal rules

Conversions defined by a URL instead of by code — and counted retroactively.

A goal rule says "any visit to /thank-you is a signup". No code on the site, and it applies to traffic you already collected.

Two ways to record a conversion

A rule

A stored definition, evaluated when a report is read. Counts the past. Cannot carry a value or properties.

A sent goal

An event recorded the moment it happens, from the script or POST /goals. Counts from now on. Can carry a value and properties.

Both appear together in breakdowns by goal — one list, as the dashboard shows them.

Retroactive, measured

A rule created minutes ago reported 530 visitors and 868 conversions over the previous thirty days. The pageviews were already there; the rule only decides what to call them.

That has a consequence worth holding onto:

Editing a rule rewrites history. Change match_value from /thank-you to /thanks and every past figure for that goal changes with it, the next time anybody looks. Renaming does the same from the other end — the old name disappears from every breakdown it ever appeared in.

It is what makes rules forgiving: fix a typo and last month becomes right. It is also why a number somebody screenshot last week may no longer match.

Deleting takes the figures too

There was never a stored conversion to keep. Delete the rule and the goal disappears from every window at once, not just from today.

If you need a conversion that stays on the record whatever happens later, send it as an event instead.

Paths, not URLs — but paste either

match_value is a path, because that is what gets stored. Out of habit people paste the full address, so it is converted rather than refused:

https://example.com/pricing   →   /pricing

Query strings and fragments are dropped — they were never stored, so /pricing?utm=x would have matched nothing.

Match types

Matches
equalsExactly that path
starts_withThat path and anything under it
containsThe value anywhere in the path

There is no wildcard, deliberately. starts_with and contains do the same job more readably, and a mistyped wildcard pattern produces an empty goal silently — a bug that raises no error and looks like "nobody converted".

Names

Lowercase letters, numbers, and _ - : — the same pattern as a code-sent goal, so a rule can later be moved into code without renaming it.

Unique per site: two goals sharing a name would be indistinguishable in every breakdown, so a collision answers 409.

Was this page helpful?

Last updated September 16, 2026