The Agency Playbook: Managing Client Links in ShortlyLink
How agencies and teams organize client links in ShortlyLink using campaigns and tags as the client boundary, hand off reporting, and work within the current Teams model.
If you run link tracking for multiple clients, the fastest way to get organized in ShortlyLink today is a single shared operator account where campaigns and tags are your client boundary — not the Teams roster. Teams in ShortlyLink is a member roster: it lets you invite people by email with admin, editor, or viewer labels, but it does not yet share links across accounts, and roles don't grant cross-account permissions. So the durable agency pattern is one operator login, disciplined naming, and per-client custom domains, reporting, and conversion tracking layered on top.
Quick answer
- Use one shared operator account. Make a campaign per client (or per client offer) and a consistent tag taxonomy the real dividing lines between clients.
- Don't lean on Teams for isolation. It's a roster, not a shared workspace — links aren't shared across accounts and roles don't scope link access. Building on it burns limited beta seats and risks orphaned links when staff leave.
- Brand each client with their own custom domain (verified by DNS TXT) and pull per-campaign reporting plus CSV/JSON export for hand-off.
- Wire conversions per client through the signed postback/pixel path, and route operational alerts to webhooks and Slack so you catch problems before clients do.
Why not just use Teams for each client?
It's the obvious first instinct: invite the client, or a staffer per client, give them a role, done. But ShortlyLink's Teams today is a member roster. Inviting someone as admin, editor, or viewer records them on the roster; it does not create a shared link workspace, and it does not hand another account access to the links that live under your operator login. Links belong to the account that created them.
That has two practical consequences for an agency:
- You'd burn beta seats for isolation you don't actually get. ShortlyLink is in beta with limited spots. Spending invitations to approximate a workspace that isn't there yet is a poor trade.
- You create orphaned links. If each client's links live under a different individual's account and that person leaves — a contractor rolls off, a media buyer changes agencies — the links, their history, and their short codes go with the account. Redirects you're responsible for end up outside your control.
Keep everything under one operator account and you sidestep both problems. The client boundary moves into metadata you fully own: campaigns and tags.
How should you structure campaigns and tags?
Think of campaign as the primary folder and tags as the cross-cutting filters. A campaign is where you group a client's links so per-campaign reporting and exports line up cleanly with what you'll hand back. Tags let you slice across campaigns — by channel, by offer, by funnel stage — without breaking the client grouping.
A workable convention:
- Campaign = client, or client + offer. For a small client, one campaign named for them is enough. For a client running several distinct offers, split by offer so reporting stays legible:
acme-summer-sale,acme-evergreen-webinar. - Tags = everything you'll want to filter on later. Lock in a taxonomy on day one and apply it everywhere:
- Client:
client:acme(redundant with the campaign, but priceless when you filter across campaigns) - Channel:
ch:facebook,ch:tiktok,ch:email,ch:youtube - Offer/funnel:
offer:trial,funnel:tof,funnel:bof - Owner:
owner:priyaso you know internally who built and manages a link
- Client:
The payoff shows up at bulk-import time. ShortlyLink imports up to 500 links per request (rate-limited to roughly 10 imports per hour), and a bulk import applies a shared campaign, tags, domain, expiry, and UTMs across every row, with per-row error reporting. So a client's whole launch — one campaign, one tag set, one branded domain — goes in as a single, consistent batch. The naming discipline you set up front is what makes that batch, and every report after it, clean.
For custom short codes, keep the same discipline. Auto codes are 8 characters; custom back-halves are 3–50 characters (letters, numbers, _ and -), must be unique, and block reserved words. Lookups are case-insensitive, so Acme and acme collide — pick one casing and stick to it. See features for the full link-management surface.
How do you brand links per client?
Each client should get short links on their own domain, not a shared one. In ShortlyLink you add a custom domain, verify ownership with a DNS TXT record, and then assign that domain per link. So go.acme.com/spring serves Acme's traffic while a second client runs on theirs — same operator account behind the scenes, distinct brand in front of every audience.
Custom domains do more than look right:
- Trust and click-through. A recognizable domain reads as legitimate to the client's audience.
- Portability of perception. The client sees their brand on every link even though you operate them.
- Clean separation in the wild. Anyone auditing a client's links sees only that client's domain.
Pair this with the publishing surfaces where they help. Pre-sell and bridge pages live at /p/:slug with view and CTA tracking, and white-label lets you hide the Shortly footer so a client-facing bridge page stays on-brand.
How do you report per client and hand off data?
Because each client is a campaign, per-campaign reporting is your default view, and it maps one-to-one onto what you deliver. ShortlyLink's custom dashboards offer 19 widget types — totals, unique visitors, conversions, conversion rate, revenue, clicks-over-time, breakdowns by country, city, region, device, browser, OS, referrer, UTM source, UTM campaign, and source, plus top links and landing-page views/engagement. Build a client dashboard once with presets up to about six months (or custom ranges) and reuse it.
For hand-off, export CSV or JSON: up to 10,000 rows by default, a hard max of 100,000, with truncation clearly announced when you hit it. A few things that make agency reporting trustworthy:
- Bot traffic is excluded from stats automatically, so the numbers you send clients reflect real humans.
- City-level geo is keyed with country, so London, UK and London, Canada don't get merged in a client's regional breakdown.
- Traffic source is distinguished — a raw link click, a QR scan (
source: qr), and a link-in-bio tap are counted separately, so channel attribution in a report holds up. - No cookies or localStorage are used for click tracking; the visitor fingerprint is a one-way server-side hash — a clean answer when a client asks about privacy.
Filter an export by the client's campaign (or client: tag), and you have a defensible, self-consistent dataset for the monthly deck.
How do you track conversions and revenue per client?
Reporting clicks is table stakes; agencies get renewed on conversions and revenue. ShortlyLink takes two inputs down one signed path: a server-to-server postback (GET /postback) and a browser pixel (POST /api/conversions/pixel).
Here's the mechanism to get right per client. Every redirect appends a click id (cid), an expiry (exp), and an HMAC-SHA256 signature (sig) to the destination URL. The client's network (or thank-you page) must read those values back and return them on the postback or pixel. Key rules:
- Signatures expire after 24 hours — conversions that report later are rejected, so make sure each client's postback fires promptly.
- Dedup is by click id — a repeat returns HTTP 409, so you won't double-count a client's sales.
- Payouts are clamped to the link's
maxPayout(or a default max of 1000); negative, NaN, or Infinity amounts become 0. SetmaxPayoutper client offer so a misconfigured feed can't inflate revenue. - Statuses normalize to confirmed, pending, or rejected.
Conversions and revenue land in the same dashboard and CSV export, and you can turn on conversion webhooks to push each one into a client's own system in real time.
How do you stay on top of problems across clients?
Running many clients from one account means you need alerting that scales. ShortlyLink emits webhooks for click, conversion, bot_detected, link_expired, and anomaly events, HMAC-signed and SSRF-guarded. The Slack integration delivers conversion and anomaly alerts and adds a signature-verified /shortly slash command.
Wire these so nothing rots quietly:
link_expiredmatters because ShortlyLink supports scheduling —startsAtto activate,expiresAtto auto-expire, plus an on/off toggle. When a client's promo link expires, you want to know before they do.anomalyandbot_detectedsurface fraud fast. An anomaly job runs every five minutes and flags traffic spikes and bot surges, routing to in-app and Slack alerts.conversionalerts give you a live pulse on which client offers are actually converting.
One operational gotcha to remember and to tell your team: fraud scoring will block a curl request with a 403. If you test a client's link from the command line it trips the block tier. Test in a real browser instead.
Shared operator account vs. the alternatives
| Approach | Pros | Cons |
|---|---|---|
| Shared operator account (campaigns + tags as client boundary) | You own every link; no orphaning when staff leave; no beta seats spent on isolation; one place to report and export; consistent domains, conversions, and alerts | Discipline is manual — naming and tagging must be enforced; no built-in per-client access walls yet; everyone with the login sees everything |
| Account per client | Hard data separation; a client could in principle be handed their own login | Multiplies logins to manage; no cross-client rollup; links live under each account, so switching operators means migration; heavier during beta |
| Account per operator/staffer | Feels like "each person owns their work" | Highest orphaning risk — links leave with the person; no shared reporting; fragments a single client across several accounts |
For today's product, the shared operator account wins on the things that actually bite agencies: ownership continuity and clean rollups.
What to revisit if Teams changes
This playbook is honest about a beta product. If ShortlyLink's Teams evolves from a roster into a true shared workspace — links shared across accounts, roles that actually scope link access — several trade-offs flip. You'd then be able to give staff genuinely separate, permissioned access instead of sharing one login, and per-client isolation could move from tags into real boundaries. Until that ships, keep the client boundary in campaigns and tags, keep everything under one operator account, and lean on custom domains and per-campaign exports for the client-facing polish. Watch the FAQ for how the Teams model develops.
Ready to set up your first client campaign? Start free at /register — no credit card, beta access.