Skip to content
metryo

01Quick start

Install Metryo in minutes.

Create a website in your dashboard, copy your snippet, and paste it before the closing </head> tag. Data appears within seconds of the first visit.

index.html
<!-- Add before the closing </head> tag -->
<script
  defer
  data-site="site_xxxxx"
  src="https://cdn.metryo.io/m.js">
</script>

Replace site_xxxxx with the site ID from your dashboard — everything else is copied as-is.

02Custom events

Track the actions that matter.

Pageviews are automatic on every plan. For everything else — signups, purchases, downloads — call metryo.event() from anywhere in your code. Available on all plans, including Free.

From JavaScript

anywhere.js
// Track any action with one call — from an onclick,
// a form submit, or anywhere in your code.
metryo.event("Signup completed");

// Attach properties: strings, numbers and booleans only.
// Up to 20 per event, names trimmed to 60 characters and
// values to 300. Arrays, nested objects, NaN and Infinity
// are dropped before the request is sent.
metryo.event("Checkout started", {
  plan: "growth",
  value: 15,
});

From HTML

index.html
<button onclick="metryo.event('Pricing CTA clicked')">
  Start for free
</button>

Single-page apps

spa.js
// Mostly nothing to do. The script hooks pushState and
// popstate, so router.push() and the back button are
// tracked automatically — query string included, so
// ?page=2 counts as its own pageview.
//
// history.replaceState is treated differently on purpose:
// it counts only when the PATH changes. Apps also use it
// to write filters and tabs into the query on every
// keystroke, and counting those would put a pageview on
// each letter typed into a search box.
//
// So if you paginate or filter with router.replace(),
// call this yourself at the point you know it is a real
// navigation:
metryo.pageview();

Calling before the script loads

index.html
<!-- Only needed if you call metryo.event() before the
     script has finished loading — with defer, async, or a
     tag manager. Put this above the script tag. -->
<script>
  window.metryo = window.metryo || {
    q: [],
    event: function (n, p) { this.q.push(["event", n, p]); },
    pageview: function () { this.q.push(["pageview"]); }
  };
</script>

03Click tracking · Paid plans

Measure clicks without writing code.

On any paid plan the script also records clicks on its own. Mark an element with data-metryo-event and it is tracked by name; outbound links and file downloads are detected with no markup at all.

Click tracking is available from the Starter plan upwards. On the Free plan these events are discarded and never count towards your monthly allowance — metryo.event() keeps working on every plan.

Naming a click

index.html
<!-- Name a click yourself: no JavaScript needed -->
<button data-metryo-event="Add card">
  Add card
</button>

<!-- Attach properties with data-metryo-prop-*
     Use lowercase, hyphen-separated names. HTML lowercases
     every attribute, so data-metryo-prop-planName would
     arrive as "planname" — write plan-name instead. -->
<button
  data-metryo-event="Signup started"
  data-metryo-prop-plan="growth"
  data-metryo-prop-signup-position="hero"
>
  Start for free
</button>

<!-- Opt an element out entirely -->
<a href="https://example.com" data-metryo-ignore>Ignored</a>

Detected automatically

  • Outbound link — any link to a different hostname, with the destination domain, its path and the link text as properties. The query string is never sent: it routinely carries session tokens and email addresses.
  • File download — links ending in a document, archive, installer or media extension, with the file name attached.
  • In-page anchors and mailto: or tel: links are skipped, so they never consume your allowance.

Turning detection off

head.html
<!-- Keep marked elements only: no outbound or download
     tracking -->
<script
  defer
  data-site="site_xxxxx"
  data-auto-clicks="off"
  src="https://cdn.metryo.io/m.js">
</script>

04Goals & conversions · Paid plans

Turn an action into a conversion rate.

A goal is a page reached or an event fired that you count as a conversion: the thank-you page, a signup, a download. The dashboard shows how many visitors converted, how often, and at what rate of all visitors — and can be filtered to just the visitors who did.

Goals are available from the Starter plan upwards, up to twenty per website. They are evaluated when the dashboard is read, so a goal you add today reports on last month as well.

Event goals

signup.js
// 1. Send the event from your code (or mark a button with
//    data-metryo-event="Signup completed" on a paid plan).
metryo.event("Signup completed", { method: "github" });

// 2. In Site settings → Goals, add a goal:
//      Counts when:  An event fires
//      Event name:   Signup completed
//
// The dashboard now shows unique conversions, total
// conversions and the conversion rate — and the goal works
// on events you already stored, not just new ones.

Page goals

site settings → goals
Counts when:  A page is viewed
Page path:    /thank-you          exactly that page
Page path:    /blog/*             every page under /blog/

No code change: pageviews are already collected, so a page
goal reports the moment you save it.
  • Uniques — visitors who converted at least once in the period. The conversion rate is uniques divided by all visitors in the same period, under the same filters.
  • Total — every conversion, repeats included. For a download or a search, the repeats are the point.
  • Click a goal and the whole dashboard shows only the visitors who converted: where they came from, what they read first, which device they used.

05Filters

Every row is a question.

Click a page, a source, a country, a browser or an event and the entire dashboard — every metric, the chart and every list — is recomputed for that segment. Filters combine, sit in the URL, and are on every plan.

In the URL

dashboard URLs
# One filter per dimension, as f=key:value — bookmark or share it
/app/site_xxxxx?range=30d&f=country:Germany&f=device:mobile

# Sources, channels and campaigns filter the whole session
/app/site_xxxxx?range=7d&f=refDomain:news.ycombinator.com

# Events and goals filter to the visitors who did the thing
/app/site_xxxxx?range=30d&f=goal:66f1a2…

How each kind applies

  • Page, country, device, browser… — matched on every event, so “Germany” means every pageview and event from a visitor in Germany.
  • Source, channel, UTM — where a session arrived from is only known on its first pageview, so these select whole sessions: everything a visitor from Hacker News did, not just the page they landed on.
  • Event, goal — select the visitors who did the thing, then show everything those visitors did in the period. “What do people who sign up read first?” is one click.
  • Click a highlighted row again to remove its filter, or use the chips above the dashboard. Changing the date range keeps the filters.

06Sharing & reports · Paid plans

Give the numbers to the people who need them.

A shared link shows a live, read-only copy of a website's dashboard to anyone who has it — a client, a partner, a board. The weekly report puts last week's numbers in your inbox every Monday. Both are available from the Starter plan up.

Shared dashboard links

  • Create one in Site settings → Shared dashboard links. The link is 32 random characters — impossible to guess, so the link itself is the key. Give each one a label so you know who has it.
  • Viewers get every tab, the date picker and the filters, exactly as you see them. They do not get export, settings, the live count or anything about an individual visitor — every number is an aggregate.
  • Revoke a link and it stops working on the next load, for everyone who had it. Up to ten live links per website.

Weekly email report

  • Switch it on per website in Site settings → General. Every Monday morning you get last week's visitors, pageviews, sessions, bounce rate and session length, each with the change on the week before.
  • Plus the five busiest pages, the five biggest sources and — if you have defined any — your goal conversions for the week.
  • Weeks run Monday to Sunday in UTC. One email per website; an agency with thirty properties turns it on for the three it is working on.

07Script options

Everything the tag accepts.

The script needs only data-site. The rest are attributes for the cases that need them, and one localStorage key for keeping your own visits out of your numbers.

head.html
<script
  defer
  data-site="site_xxxxx"

  data-hash="on"            <!-- count #/route changes as pageviews -->
  data-auto-clicks="off"    <!-- keep marked elements only (paid plans) -->
  data-api="https://cdn.metryo.io/api/collect"  <!-- only if you self-host m.js -->

  src="https://cdn.metryo.io/m.js">
</script>

<!-- Exclude your own browser from every site you own -->
<script>localStorage.setItem("metryo_ignore", "true")</script>
  • data-hash="on" — for apps that route with the URL fragment (/#/settings). Each fragment change counts as a pageview and the fragment is part of the page path. Off by default, because on ordinary sites a fragment is a heading.
  • data-auto-clicks="off" — stops outbound-link and download detection. Elements you marked with data-metryo-event are still tracked.
  • data-api — where beacons are sent. Only needed when the script is served from somewhere other than Metryo; by default it is derived from the script's own URL.
  • metryo_ignore — set this localStorage key to "true" in your own browser and the script sends nothing from it, on every website you track. Remove the key to start again.

08Reference

The collect endpoint.

The script sends a tiny JSON payload to POST /api/collect. You can also call it directly from native apps or server-side code.

FieldTypeDescription
sstringYour site ID, e.g. site_k3v9x2m4q1 (required)
ustringFull page URL, including query string (required)
rstringdocument.referrer, may be empty
w / hnumberScreen width and height in pixels
estring?Custom event name — omit for a pageview
pobject?Event properties (strings, numbers, booleans)
tstring?"click" for auto-tracked clicks — requires a paid plan

The endpoint always answers 202 so analytics can never break your page. Device, browser, country and traffic-quality signals are derived server-side; the visitor identifier is a salted hash that rotates monthly — no cookies, no raw IP stored.