Features
Cross-domain tracking
When a visitor follows a link from example.com to app.example.io, MetricRaven can keep counting them as the same visitor, so the signup or payment on the app is credited to the campaign that brought them to the landing site.
Subdomains of one domain (www, app, shop) don't need this: they share the visitor through data-domain. Use cross-domain tracking for different root domains, like a marketing site and an app, a site and a separate store, or several brand domains.
Set it up
Add every domain to the site
In Settings → General → Site, list all the domains under the same site. Visits are only accepted from these domains, and links are only joined when they come from one of them.
Install the same script on each domain
Use the same site ID everywhere, and add
data-allowed-hostnameswith your other domains, comma-separated. Listing the current domain too is fine, so the same tag works on all of them.index.html<!-- On example.com and on app.example.io: the same tag, listing the other domain(s). --> <script defer src="https://metricraven.com/js/script.js" data-site-id="YOUR_SITE_ID" data-allowed-hostnames="example.com,app.example.io" ></script>Links and forms are handled for you
When a visitor clicks a link or submits a form that leads to a listed domain (or one of its subdomains), the tracker adds a short
mr_linkparameter. The page that opens reads it, removes it from the address bar straight away and continues the visit.
Links you build in code
Navigation through window.location, window.open or a router doesn't go through a link click, so add the parameter yourself, right before navigating:
// Links and forms are linked automatically. For navigation in code, add the token first:
window.location.href = window.analytics.linkUrl("https://app.example.io/signup?plan=pro");
// Or append the parameters yourself (empty until the tracker has a fresh token):
const params = new URLSearchParams(window.analytics.linkParams());With the npm package:
import { init, linkUrl, linkParams } from "@metricraven/web";
init({ siteId: "YOUR_SITE_ID", allowedHostnames: ["example.com", "app.example.io"] });
// Build the URL right before navigating: tokens expire after 30 minutes.
window.open(linkUrl("https://app.example.io/signup"), "_blank");
linkParams(); // { mr_link: "…" } or {}linkUrl only changes URLs that lead to one of your listed domains, so it is safe to call on any URL. It returns the URL unchanged until the tracker has its first response. See NPM package.
Privacy model
No visitor ID ever appears in a URL. The parameter is an opaque token that only MetricRaven's server can read, and it is useless anywhere but in the browser it was made for.
| Rule | Why |
|---|---|
| Encrypted and signed | The token holds the visitor ID and an expiry, encrypted and authenticated by the server. Nobody can read the ID from it or forge one. |
| Bound to one browser | It only opens for a request from the same IP address and browser it was issued to. A copied, shared or bookmarked link doesn't merge someone else into the visitor. |
| Short-lived | It expires 30 minutes after it was issued. The tracker keeps it in memory only and refreshes it with each pageview. |
| Only from your own pages | The arrival page's referrer must be another of the site's domains, so a link pasted into chat or email is ignored. |
| Added at the moment of the click | Links get the parameter as they are followed and lose it right after, so the token isn't left in your page or in copied links. |
Consent works the same as on a single domain:
- No consent on the receiving domain: nothing is stored in the browser there. The server remembers that this browser's daily ID on that domain belongs to the linked visitor until the end of the UTC day, the same lifetime as the daily ID itself, then forgets it.
- Consent on the receiving domain: the visit continues with the linked visitor's ID, as subdomains do with the shared cookie. If the visitor only had a daily ID on the first domain, today's visits from it join this domain's consented ID, just as visits from before consent do on one domain.
- Consent granted later on the receiving domain: the stored ID becomes the linked visitor's, so the journey stays in one piece.
See Consent & visitor IDs for how IDs work before and after consent. Deleting a person also deletes these same-day links.
Verify it works
On the first domain, add ?metricraven_debug=1 to the URL and open the console: it lists the linked hosts. Click through to the other domain: the address bar shows no mr_link, and in Traffic → Visitors the visitor's journey shows pages from both domains.
Details
- Clicks to your listed domains aren't counted as outbound clicks. Visits between them aren't referrals.
- GET forms carry the token as a hidden field; other forms carry it on their action URL. Both are removed right after submitting.
- Linking needs the browser to send a referrer. The default policy does; a page with
Referrer-Policy: no-referrercan't link. If you proxy the tracker on one domain only, forward the visitor's IP (x-visitor-ip) so both domains see the same address. See Proxy. - A token that is expired, from another browser or not from one of your domains is ignored silently and the visit counts as a new visitor. Debug mode logs it.
- Native apps don't use this. To join web visits to app users, use identify on both.