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.
- Add one Source (
facebook) and one Medium (social) in Vocabularies. - Create a Campaign (
Spring launch) and pick those as defaults. - 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. - 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.
Links
A link is a short URL (7 chars on the system domain, 5 on custom domains) that 302s to a target URL with the UTM parameters baked in. Short codes are random base62 by default; you can also reserve a vanity slug.
Short URL: https://sho.fi/aZ3k9Pp
Redirects to:
https://your-site.com/landing?utm_source=facebook&utm_medium=social&utm_campaign=spring-launch
Expiry + click limits
Optional: set expires_at on a link, after which it 410s
with a branded "link expired" page. Or set a click limit — same treatment once exceeded.
Useful for flash promos.
QR codes
Every link has a QR code (SVG + PNG). Open the link detail page → QR button.
Export
The Links page has an Export dropdown with three formats: CSV (opens in Excel & Sheets), TSV (tab-separated — Excel imports it without the quoting dance), and JSON (array of typed records for programmatic use). All three respect the current filters (campaign, status, search query) and stream page-by-page so they scale past 200k rows.
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.
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
- Workspace switcher → Domains → add hostname.
- Add either a CNAME (recommended) or a TXT record at
_shortifi-verify.<your-host>. - Hit Verify. Once verified, TLS is provisioned on-demand by Caddy.
- 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.
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 / user | 1 | 5 | ∞ |
| Campaigns / workspace | 5 | 200 | 2000 |
| Active links / workspace | 100 | 10k | 200k |
| Custom domains | 0 | 1 | ∞ |
| API keys / workspace | 1 | 5 | 25 |
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.