Skip to main content
A creator link is a vanity URL that EVO owns the redirect for. Every hit is recorded before the visitor is forwarded, which is what mints the click token the rest of the system depends on.
  • Domain — a host registered as an AttributionDomain. A link can only use a registered domain.
  • Slug — lowercase a-z0-9_-, up to 64 characters. Required on shared domains, optional on a custom domain.
A custom domain can use the root, so getdupe.app with an empty slug is a valid link — that is what a creator says out loud on camera. Non-root slugs are for bio links and per-creator variants. An unknown slug on a known domain falls back to that domain’s root link, so a mistyped or stale path still lands on the product page and still counts a click. App links always use the EVO engine. Web links may instead use the airbridge engine, which forwards through an Airbridge tracking link and lets Airbridge own the touchpoint.

What happens on each device

1

The hit reaches the redirect app

Any non-EVO host pointed at the Dialed frontend is treated as an attribution host and rewritten to /l/<host>/<path>. There is no per-domain allowlist to update.
2

The click is recorded

The route posts the domain, slug, query string, referrer, user agent, country, and visitor IP to POST /api/public/attribution/clicks with a 4-second timeout. The backend returns the redirect URL, click token, detected platform, link type, and brand name.
3

The visitor is forwarded

Desktop and unknown platforms get a 302. Phones on an app link get the smart install page instead.

Desktop or unknown platform

A 302 to the destination URL with the click token and UTMs appended. For an app link with no configured store URL for that platform, the same web fallback is used. Store pages are the exception: an App Store or Google Play destination is forwarded untouched, because Apple and Google ignore the query string and the attribution happens in the app via the SDK instead. EVO serves a small “Get Brand” page with a single Get the app button. There is no auto-redirect, on purpose: the clipboard handoff only works inside a real tap, and it is what turns a probabilistic IP match into a deterministic one. Tapping the button copies the evc_… click token to the clipboard, then opens the store:
  • iOS — the App Store URL, with ?mt=8 appended when it has no query string.
  • Android — an intent://details?id=<package> URL with S.browser_fallback_url set, when the package can be parsed from the Play URL’s id parameter. Otherwise the plain Play URL.
After 2.5 seconds the page shows “Not opening? Tap the button again.”

TikTok, Instagram, and other in-app browsers

When the user agent looks like an in-app webview (Instagram, Facebook, Messenger, TikTok, Snapchat, Twitter, LinkedIn, Pinterest, Line), the page also renders a hint card telling the visitor how to escape it: On iOS the card also offers a direct Open in Safari link built from the current page URL.
Clipboard access inside an in-app webview is unreliable. When the token does not survive, the install still resolves through the creator code or the 24-hour hashed-IP fallback — see Creator codes.
If the click cannot be recorded, the visitor still lands somewhere real. The route falls back to the per-domain URL in ATTRIBUTION_FALLBACK_URLS, and if that is not configured, renders a link-not-found page with a 404. Attribution is lost; the visitor is not.

UTM passthrough

Incoming UTMs on the vanity URL are stored on the click and forwarded to web destinations. EVO fills in defaults only for keys the incoming URL did not carry: utm_source, utm_medium, utm_campaign, utm_content, and utm_term are all recorded on the click row. The rest of the incoming query string is forwarded too — except a replayed evo_cid, which is always stripped and replaced with the freshly minted token.

Shared vs custom domains

Shared domains require a slug precisely so several brands can safely share one host. tryapp.link/overcomer and tryapp.link/dupe can coexist; a root link on a shared host cannot.

Connecting a custom domain

From the client portal, Results → Attribution → Domains, enter a domain you own. EVO registers it, attaches it to the Vercel project, and returns the exact DNS records to create.

DNS records

Vercel’s rank-1 recommendation replaces those defaults when it returns one. An unverified domain also gets a TXT verification challenge in its dns_records list — create that too.

Statuses

Press Check to re-run verification after your DNS changes propagate. Removing a domain that still has links returns domain_has_links (409) with the offending links — delete or move them first.

For the EVO team

Registering a shared domain

Shared domains are registered from Sales Attribution → Domains in the admin console (POST /api/internal/attribution-domains with kind: "shared" and no brand). A shared domain must not have a brand; a custom domain must. The app’s own hosts are rejected: anything on evomarketing.co or vercel.app cannot be registered as an attribution domain.

Cloudflare automation

For EVO-owned shared domains, the required A, CNAME, and TXT records can be created in Cloudflare automatically once Vercel reports them. After the records are upserted, EVO re-checks Vercel in the same request so a newly verified domain can go active immediately. Custom client domains are never changed in Cloudflare. A missing zone or an unset token simply leaves the Vercel status and the manual dns_records instructions intact.

Environment variables