Documentation

Welcome

Shortifi is a UTM-aware URL shortener. Every short link you create has its utm_source, utm_medium, utm_campaign, utm_content and utm_term parameters baked into the destination URL — so the analytics in your destination tool (Google Analytics, Plausible, Mixpanel, …) match what Shortifi shows.

The product is organized into workspaces (one per project you're promoting), each holding vocabularies (reusable UTM values), campaigns (containers that share a utm_campaign), links (short URLs with analytics), and a team.

Three-minute setup
  1. Add one Source (facebook) and one Medium (social) in Vocabularies.
  2. Create a Campaign (Spring launch) and pick those as defaults.
  3. Open Links → New link, paste a target URL, hit Create. Your short URL now redirects to your-target?utm_source=facebook&utm_medium=social&utm_campaign=spring-launch.
  4. Share. Within ~60 seconds of the first click, the Analytics tab shows the result.

Workspaces

A workspace is the container for one project you're promoting — a website, an Instagram account, a podcast. Everything else (campaigns, links, vocabularies, custom domains, analytics, team) lives inside exactly one workspace and is invisible from any other.

Per-user cap

Free users own one workspace. Pro users can own up to five. Business users have unlimited workspaces. The cap is computed from your highest plan across any owned workspace — owning even one Pro workspace lifts the cap to 5 immediately.

Switching + creating

Click the workspace block at the top of the sidebar to open the switcher dropdown. From there: Manage team for the active workspace, a list to switch between workspaces, or + Create workspace at the bottom.

Data isolation

A teammate added to your sprache.app workspace doesn't see anything from your personal-blog workspace, and vice versa. Roles are per-workspace: the same user can be owner of one and viewer of another.

Campaigns

A campaign groups all the links from one marketing push. Its slug becomes the utm_campaign value baked into every link inside it. The defaults you set on the campaign (source, medium, content, term, color) pre-fill the new-link form, so you don't pick the same values over and over.

Slug is immutable

Once a campaign is created, its slug is frozen. If you rename the campaign, the slug stays — old links keep their utm_campaign value, analytics history doesn't break.

Archive vs delete

Archiving a campaign hides it but keeps it queryable for historical analytics. Deleting from the archived view is permanent — referencing links survive (their utm_campaign string stays intact) but the foreign key on each link is set to NULL. See the Archived → Delete permanently bulk action.

Color

Pick a campaign color from the palette popover (17 hues × 3 shades). It shows up as a dot next to the campaign name and is used in analytics breakdowns to keep campaigns visually distinguishable.

Vocabularies

Vocabularies are reusable values for the four UTM dimensions: source, medium, content, term. They keep facebook from drifting into Facebook or fb across links — the link builder autocompletes against your vocabulary list, so the same value is reused everywhere.

Key vs label

The key is the slug-cased value that goes into the URL (facebook). The label is what shows up in dropdowns and analytics breakdowns (Facebook). The key is immutable after creation; the label can be renamed any time.

Archive vs delete

The unique index on (workspace_id, kind, key) includes archived rows — so an archived facebook source still blocks re-creating facebook. That's intentional: stops historical UTM values from silently changing meaning. To free up the key slot, archive then delete permanently.

Bulk + templates

The bulk builder generates many links in one go from the cross-product of vocab values you pick. Open Links → New link and switch the toggle from Single to Bulk.

Example bulk run

Sources: facebook, twitter, linkedin
Mediums: social
Content: feed, story
→ 3 × 1 × 2 × 1 = 6 links in one shot, each with a unique short code.

Templates

Above the form: Start from a template. Pick from Social campaign / Paid ads / Email newsletter — Shortifi pre-selects every vocab item in your workspace whose key matches the template. Any missing keys are listed in a toast hint so you can create them and re-apply.

Cap

Each bulk request creates at most 500 links. The builder shows the count live and refuses to submit past the cap.

Analytics

Click data lands in the dashboard within ~60 seconds of being captured. The pipeline is: redirect → Redis stream → consumer → partitioned click_events → aggregator → daily roll-up table → KPIs.

What you see

  • KPI cards: total clicks, bot clicks, active days.
  • Time-series chart with 24h / 7d / 30d / 90d presets.
  • Top-N breakdowns: sources, mediums, countries, devices.
  • Per-campaign + per-link drilldowns.
  • CSV export of aggregates.

Bot detection

The user-agent parser flags obvious bots (curl, wget, crawlers, spiders). Hide-bots toggle excludes them from totals by default — they still get stored, just rolled into a separate bucket.

Privacy

We never store raw IP addresses. They're hashed with a daily-rotating salt so click rows can't be linked back to individuals, and only the country/region/city are kept (when a GeoIP database is configured).

Custom domains

Pro plans get one custom domain per workspace; Business plans get unlimited. Serve links from your own hostname (links.acme.io) instead of the shared sho.fi.

Setup

  1. Workspace switcher → Domains → add hostname.
  2. Add either a CNAME (recommended) or a TXT record at _shortifi-verify.<your-host>.
  3. Hit Verify. Once verified, TLS is provisioned on-demand by Caddy.
  4. New links on this domain get 5-char short codes (vs 7 on the system domain) because the namespace is per-workspace.

Auto-disable

We re-verify active domains weekly. After 3 consecutive failures the domain auto-disables (links 410). Bring it back with a fresh DNS record + manual verify.

API keys

API keys give programmatic access to every authenticated route. They live under Account settings → API keys.

Using a key

Authenticate any API call with the Authorization: Bearer sk_<prefix>.<remainder> header. The full secret is shown once at creation — save it now, you can't retrieve it later (only the prefix is stored alongside the Argon2id hash).

Quotas

Free: 1 active key. Pro: 5. Business: 25. Revoked keys stop working immediately and don't count against the cap.

Plan & billing

Workspace plans (Free / Pro / Business) are per workspace — each workspace's billing is independent. Pro and Business have an expiry date; when expiry passes, the workspace reverts to Free quotas automatically.

How to upgrade

Currently via coupon code: Account settings → Plan & billing, paste the code, submit. Codes stack — if you're already on Pro, redeeming another Pro code extends your expiry forward.

Quotas at a glance

Limit Free Pro Business
Workspaces / user15
Campaigns / workspace52002000
Active links / workspace10010k200k
Custom domains01
API keys / workspace1525

Team + roles

Every workspace has its own team. Invite members by email — they receive a link that's valid for 7 days; clicking it walks them through signing up (or logging in) and joining the workspace. Roles are per-workspace.

Role matrix

  • Viewer: read campaigns, links, analytics.
  • Editor: + create/edit/archive/delete links and campaigns.
  • Admin: + manage vocabularies, API keys, and teammates (except owner).
  • Owner: + workspace settings + billing. One per workspace.

Tips & shortcuts

Sidebar tricks

  • Topbar arrow icon collapses the sidebar to icons-only.
  • The user card at the bottom always links to Account settings.
  • The workspace block (top of sidebar) shows current role + plan. Click for Manage team and switching.

Theme

Account settings → Appearance. Pick Light / Dark / System. The choice is persisted per browser.

Bulk URL builder

Hit the Bulk toggle on New link to cross-product vocab values. Templates above the form populate it in one click.