Conversion tracking with QR codes and short links
Conversion tracking with QR codes and short links closes the loop from scan or click to revenue. Server-side postbacks, attribution windows, and integrations.
Conversion tracking with QR codes and short links is the part of campaign measurement that most teams set up halfway and then quietly stop trusting. The scan happens. The click logs. The signup or the purchase or the download lands on a different system. Nobody joins the two records and six months later "where did that customer come from" is a guess dressed up as a number. This is the post that walks the actual pipe — from the moment a phone camera fires at a printed code to the row in your CRM that says "yes, this person paid us, and it started on the spring magazine ad" — and the small set of integration choices that decide whether the loop closes or stays open.
The reason it matters: a scan or a click is a cheap signal. A conversion is the expensive one. Reporting just the cheap signal is what kills print campaigns, kills referral programs, and kills the budget for the QR codes that are actually working. If you can tie the conversion back to the original surface — the poster, the magazine page, the SMS, the receipt — you can spend more on the surfaces that pay back and stop spending on the ones that don't. The same dynamic shows up upstream too: the hidden cost of not tracking your short links breaks down what untagged campaigns quietly cost before you even get to the conversion layer. Everything below is the plumbing that makes the loop closeable without you having to write a custom analytics warehouse.
What conversion tracking with QR codes and short links actually means
A conversion is whichever event downstream of the scan or click you care about. It's intentional that the definition is loose — for an e-commerce store it's a purchase, for a SaaS it's a paid signup, for a charity it's a donation, for a SaaS trial it's a qualified email submission. The mechanics of tracking it are identical regardless. Three things have to be true:
- The original click carries an identifier. Usually a UTM bundle or a short link slug, sometimes a one-time per-recipient token, sometimes both. If "UTM" itself is unfamiliar, the beginner's guide to what a UTM parameter is covers the five fields and how each one shows up in GA4 before any conversion plumbing matters.
- The identifier survives until conversion. This is where most setups fall over — the identifier needs to ride through cookies, session storage, or a first-party tag from the landing page through to the moment payment clears or the form submits. Before the identifier can survive anywhere, the redirect has to capture and emit it — the primer on how to track QR code scans covers what the scan event records at hop one and what it doesn't, which is the data the conversion side then has to keep alive.
- The conversion event sends a signal back. Server-side ping, postback URL, webhook, pixel — whichever shape your stack uses to say "this user, who came in tagged X, just did the thing."
That third step is the one that's frequently missing. Without it, you can see which links got clicked but not which clicks made money. With it, the chain is intact and the rest is mostly hygiene. The chain only stays intact when scan-side and click-side data live in one log to begin with — the structural reason a QR code platform with short links built in carries attribution that two separate tools can't reassemble cleanly.
The two attribution models you can pick from
Before any plumbing, decide which model you're running. The honest options are last-click and first-touch, with a small set of teams running multi-touch.
Last-click. The conversion is attributed to the most recent tagged click before the conversion event. Simple, defensible, what most analytics tools do by default. Works well when the customer journey is short (someone scans a QR on a flyer, lands on your site, buys within an hour).
First-touch. The conversion is attributed to the very first tagged click in that browser's history. Better for slow-burn purchases — a B2B SaaS where someone scans a conference QR in March and converts in July after a dozen other touchpoints. The first-touch signal is what tells you the conference was the original source even though the conversion landed via an email re-engagement.
Multi-touch (linear, time-decay, position-based). Splits the credit across every tagged click in the journey. Honest for long journeys, harder to act on — "this conversion was 23% the QR, 34% the email, 43% the retargeting ad" is a true statement that tells you nothing you can change.
For QR codes and short links specifically, last-click is the right default. Switch to first-touch only when you've measured an average path length of more than three tagged touchpoints. Skip multi-touch unless you have a dedicated analyst — the cost of building it is rarely repaid by decision-making clarity.
The identifier the conversion needs to carry
The click side is the easy part. Your link or QR points at yourdomain.com/p/spring?utm_source=poster&utm_medium=print&utm_campaign=spring-launch. The redirect server logs the click with all that metadata, then sends the visitor to the landing page with the query string intact. Assemble that tagged URL once with the UTM link builder so the values are lowercased and hyphenated automatically — manual typing is where the source/medium drift in. The UTM parameters that actually matter post covers what to put in each field — for conversion tracking specifically, three things must be true of the link:
- Every link in a campaign carries a unique source/medium/campaign combination. "spring-launch" alone isn't enough. "poster/print/spring-launch" tells you the channel; "social/twitter/spring-launch" tells you the digital one; without both, you can't separate the print conversions from the digital ones.
- The slug itself is also unique per surface.
yourdomain.com/p/spring-posterandyourdomain.com/p/spring-socialgive you attribution even if the destination strips UTMs (which some destinations do — see the short link not tracking clicks debug guide). Belt and braces. - The slug is short enough to print cleanly. A short URL prints better on packaging, on flyers, on small QR codes; the slug doesn't have to encode every detail because the UTMs do.
The slug-plus-UTMs approach gives you redundancy. If the landing page eats the query string, the slug still appears in your redirect log. If the redirect log is hard to query, the UTMs show up in your web analytics. Both paths exist, and the conversion pipeline can read from whichever side is healthier on a given day.
Server-side vs client-side: pick server-side
The biggest single decision in conversion tracking is whether the conversion signal travels through the user's browser (client-side, via a JavaScript pixel) or directly from your server to the link layer (server-side, via a postback URL).
Client-side is the older default. The conversion page loads a tracking pixel — <img src="..."> or a gtag('event', 'purchase', ...) call — and that pixel tells the analytics platform that the conversion happened. Easy to set up. Increasingly unreliable. Ad blockers strip it. iOS Safari's intelligent tracking prevention nukes the cookie that joins the click and the conversion. Browser-tab crashes between checkout and the thank-you page lose the event entirely. Most platforms now report 15-30% of conversions missing on client-side pixels alone.
Server-side is what every serious team has migrated to. When the order completes, your backend sends a request directly to the link platform's API (or a webhook URL it provided) saying "click id ABC123 just produced a $47 order." No browser involved, no extension can block it, no tab crash can lose it. The trade-off is more setup — you need a backend that can fire the request, and you need to pass the click id through the funnel — but the data quality difference is dramatic.
Server-side is also the only model that handles delayed conversions cleanly. A subscription that converts at the end of a 14-day trial, a refund that fires three weeks after the purchase, a high-LTV cohort that becomes valuable in month two — all of those events happen days or weeks after the original click, when the browser session is long gone. The postback fires whenever your backend learns the news, which means a 30-day trial conversion still attributes correctly to the QR scan that started it.
What a postback request actually looks like
A postback (also called a server-to-server, or S2S, ping) is the smallest useful HTTP request — usually a GET or POST with a few query parameters identifying the click and the event. The shape varies per platform but the pattern is consistent:
POST https://yourlinkplatform.com/v1/conversions
Content-Type: application/json
Authorization: Bearer <api-key>
{
"click_id": "abc123def456",
"event": "purchase",
"value": 47.00,
"currency": "USD",
"order_id": "ORD-2026-04812",
"occurred_at": "2026-05-12T14:23:01Z"
}
The link platform looks up the click by id, finds the original campaign/source/medium/UTM bundle, and records a conversion event against that row. From then on every report that shows campaign-level metrics also shows revenue and conversion count, with the original cost-per-click data intact for ROAS calculations.
Five things to get right when you wire this:
- The click id is the link. It must travel from the redirect → the landing page → the session → the backend → the postback. Most platforms generate a UUID per click and pass it as a query parameter on the destination URL; your landing page reads it from
window.location.search, stores it in a first-party cookie or session, and your backend retrieves it when the order completes. - Idempotency on
order_id. Fire the same postback twice — once on order-placed, once on payment-confirmed, once on refund-reversed — and the link platform should deduplicate by order id. If yours doesn't, you'll triple-count revenue on every retry. - Send the revenue, not just the count. A signup that's worth $9/month is a different number than a signup worth $900/year. If your platform supports a value field, populate it from the actual order total at the moment of conversion, not an estimated average.
- Time-window your postbacks. Most attribution windows are 7, 14, or 30 days from click. If you fire a postback for an order that converted 90 days after the original click, you're attributing a conversion to a campaign whose budget has long since closed. Cap the window at whatever matches your sales cycle.
- Send refunds and chargebacks too. A negative-value postback (or a
refunded: trueflag if the platform supports it) keeps your conversion totals honest. Otherwise your "best campaign" might be the one with the highest refund rate.
The attribution window question
An attribution window is the time during which a click can still be credited with a conversion. Common defaults:
- 24 hours — for low-consideration purchases (impulse e-commerce, content downloads, free trials).
- 7 days — for considered consumer purchases (mid-priced subscriptions, paid digital products).
- 30 days — for B2B SaaS trials, considered B2C purchases, anything with multi-session research.
- 90 days — for high-ticket enterprise or long sales cycles.
Three things the window controls. First, how forgiving you are about which click gets the credit — a wider window means more conversions land on the original source even when there were re-engagement touches in between. Second, how much storage and lookup overhead you incur — the platform has to keep click metadata in fast storage for the length of the window. Third, how comparable your numbers are across campaigns — switching the window mid-campaign makes period-over-period comparisons meaningless. Pick one window per business and hold it.
For print campaigns and QR codes specifically — and the QR codes in print magazines measurement post covers this in depth — wider windows are usually right. The reader who scans the QR on a Tuesday magazine reading session and converts on a Saturday afternoon laptop session is still a real conversion driven by the print campaign. A 7-day window catches them; a 24-hour window doesn't.
The interactive: which integration shape fits your stack?
Pick the integration shape that fits your stack
Pick one from each row
The recommendation updates as you choose. Your selections save locally so the answer is still here when you come back.
The verdict shifts on every combination because the right answer genuinely depends on all three axes. A coffee shop running QR codes on table tents at $4 conversions has a completely different optimum than a B2B SaaS chasing $2,400 annual contracts.
The three integration shapes you'll actually use
Across the dozens of stacks we've seen, conversion tracking boils down to three integration patterns.
Shape 1: Native postback from your backend
Your application emits the conversion event itself. Stripe webhook fires payment_intent.succeeded, your handler reads the click id from the customer metadata, fires a POST to the link platform's /conversions endpoint with order id and value. This is the cleanest pattern and the one to aim for if you control the conversion code.
Pros: highest data quality, handles delayed events, survives ad blockers and browser quirks, idempotent if you key off order id.
Cons: requires engineering time, requires the click id to ride through your funnel.
Shape 2: Webhook from a SaaS conversion tool
Shopify, Calendly, Typeform, Stripe Checkout, Memberstack — all of them emit webhooks on successful conversions. Wire a small lambda or webhook handler that translates the SaaS-shaped event into a link-platform-shaped postback. The click id rides as a custom attribute on the order, the cart, or the form submission.
Pros: no application backend required, works for no-code stacks.
Cons: depends on the SaaS supporting custom attributes (some don't), one extra hop introduces failure modes.
Shape 3: Pixel + first-party tag (fallback)
The conversion page loads a JavaScript pixel that fires the conversion event back through the user's browser. This is the only option when you don't control the backend and the SaaS doesn't emit usable webhooks.
Pros: works on basically any stack including pure-frontend landing pages.
Cons: blocked by extensions, killed by Safari's intelligent tracking prevention, lost on tab crashes, can't catch delayed conversions. Plan for 15-30% attribution loss.
Almost every stack uses some combination of all three. Backend handles the core orders, webhooks catch the SaaS pieces, pixels backstop the frontend-only flows. The skill is knowing which shape applies to which event in your funnel.
Want one platform that handles all four hops? Branded short links, QR codes, click logs with ids that survive to your backend, and a postback endpoint you can wire your conversions to. The lifetime tier covers the whole thing.
See pricing →What you should look at in the platform's analytics
A working conversion pipeline produces four views you should actually read.
Per-source conversion rate. Out of every 100 clicks from utm_source=poster, how many converted? This is the headline. Different posters in different cities, different magazines, different SMS lists all compare on this number. Watch the real-time link analytics view during a launch to catch a campaign whose CTR is high but CVR is dead — usually a landing-page mismatch you can fix in twenty minutes. For the deeper read on each individual scan-row field that feeds into per-source rates — country accuracy, device-class share, the UTC-vs-local time trap — QR code analytics — what every scan can tell you walks the column-by-column interpretation.
Per-source revenue. Conversion rate without revenue is a vanity metric. The campaign with the highest CVR might be selling the cheapest item to the cheapest customer. Sort by revenue, then by margin, then by lifetime value if you can.
Time-to-conversion histogram. The distribution of "minutes between click and conversion" by source. A bimodal histogram — half conversions in the first hour, half a week later — tells you you have two different customer behaviours coming from the same source. Worth segmenting. Video-channel acquisitions almost always sit on the longer tail of that histogram — a scanner who lands on YouTube via a printed code rarely converts in the same session, so the Channel-vs-Video-vs-Playlist-vs-Short trade-offs in the post on YouTube QR codes cover which targets produce the post-watch click-through worth chasing in the first place.
Refund-adjusted conversion rate. Conversions minus refunds, by source. Some sources convert at high rates but produce buyer's remorse — usually because the copy oversold or the offer attracted the wrong audience. The refund rate is the truth-teller.
If your link platform shows you those four cuts natively, you're set. If it doesn't, export to a spreadsheet weekly — it's still better than guessing.
How this looks on Linked.Codes specifically
The analytics tab on Linked.Codes shows clicks, sources, devices, countries, referrers, and tag-level rollups out of the box — the analytics docs cover the date-range, filter, and top-tables UI. The conversion hook is a separate endpoint: when a click resolves on a short link or QR redirect, we mint a click id and pass it through to the destination URL as a ?lc_click=... query parameter. Your landing page picks it up, your backend stores it with the order, and when the order completes, your code POSTs to /api/conversions with the click id, the value, and your account API key. The platform joins the conversion back to the original source, campaign, and tag — every report that already showed click counts now shows conversion count and revenue too.
The hooks deliberately match the cleanest of the three shapes above. We don't ship a pixel by default; for the small number of cases where a pixel is the only option, the click id is also written to a first-party cookie scoped to the destination domain, which a JS snippet on the thank-you page can read and send back via fetch. The cookie approach degrades better than a pure pixel under tracking-prevention because the cookie is first-party to the destination, not third-party to us.
What we don't ship — and probably won't — is built-in multi-touch attribution. The customers who need it have analysts who'd rather model it in their warehouse anyway; the customers who don't need it would mostly mis-use it. Last-click and first-touch cover 95% of cases and the data exports cover the rest.
The mistakes to design out before you start
Five patterns that show up in basically every conversion-tracking setup that's not working.
The click id dies at the landing page. Single-page apps sometimes strip query parameters on first paint. Read the id before any framework boots and stash it immediately. Test with a real device, not just your dev machine.
The conversion endpoint isn't idempotent. Stripe's webhook retries until it gets a 2xx. If your handler isn't keyed on order id, you'll triple-count. Make the order id the dedup key on day one.
The attribution window is too narrow. A 24-hour window on a B2B trial is the same as no conversion tracking at all. Match the window to the median click-to-conversion delay, then add 50% headroom.
Refunds aren't subtracted. Six months of attributing revenue to a campaign that produces 40% refunds is six months of bad budget decisions. Wire the refund webhook the same day you wire the conversion webhook.
Different sources use different identifier formats. The campaign field is spring_launch in one link and spring-launch in another and Spring Launch in a third. Pick a casing and separator convention — usually kebab-case lowercase — and lint your links to it. The UTM naming patterns post has the convention.
Tracking clicks is the easy half. Wiring the conversion side is what tells you which campaigns deserve next quarter's budget.
A 30-minute starting setup
If you're starting from "we have short links but no conversion tracking", here's the sequence that gets you to a working loop in an afternoon.
- Pick your attribution window. 24h, 7d, 30d, 90d. Match it to your typical click-to-conversion delay. (5 minutes.)
- Audit your links for source/medium/campaign coverage. Every active link should have all three UTMs and a unique slug. Fix any with missing or duplicated tags. (10 minutes.)
- Wire the click id through your landing page. Read
?lc_click=or your platform's equivalent on landing, store it in session. Test on a real phone. (10 minutes.) - Wire one conversion event end-to-end. Pick the simplest one — usually "trial started" or "order placed" — and post it to the link platform. Verify it shows up in the dashboard with the right source attribution. (15-30 minutes.)
- Add refunds. Same shape, negative value. (10 minutes.)
- Set a weekly check-in. Sort by conversion rate, by revenue, by refund-adjusted revenue. Three numbers, ten minutes. (5 minutes per week, forever.)
Most teams stop at step 1 and call it tracking. Steps 3-5 are where the loop closes. Everything else is polish.
Related reading
- UTM parameters that actually matter for short links — the tagging hygiene that has to come first.
- Short link not tracking clicks — debugging guide — when the chain breaks, this is the triage order.
- Real-time link analytics — watching campaigns as they happen — the live view that turns a launch into a feedback loop.
- Tracking links in email — what you can know vs what you should — the privacy line that shapes how much you log.
- QR codes in print magazines — measuring impact — print-specific attribution and what response rates actually look like.
- Click analytics — platform docs — the dashboard side of all the above.
Do I need server-side tracking if my client-side pixel works fine?
Define "works fine". If you've checked your conversion totals against your backend totals and they match within 5%, you're in good shape. If you've never checked, you almost certainly have 15-30% attribution loss you don't see. Server-side is the upgrade path when that gap matters.
What's a click id and where does it come from?
It's a unique identifier the link platform generates for every click on a tracked short link or QR code. The redirect server attaches it to the destination URL (usually as a query parameter), your landing page reads it, your backend stores it with the eventual conversion, and your conversion webhook sends it back to the platform so it can join the conversion to the original click.
How long should my attribution window be?
Match it to the median time between click and conversion in your business, then add 50% headroom. For impulse e-commerce, 24-72 hours. For mid-priced SaaS trials, 7-30 days. For high-ticket B2B, 30-90 days. Pick once and hold — switching mid-campaign breaks period-over-period comparisons.
Can I track conversions for offline sales?
Yes, with one of two patterns. Either print a unique redemption code on the landing page (tied to the click id) that staff scan at point of sale, or export weekly conversions from your CRM matched by email or phone, and import them as backdated postbacks. Both work; the first is cleaner if you control the checkout software.
What's the difference between last-click and first-touch attribution?
Last-click attributes the conversion to the most recent tagged click before it happened. First-touch attributes it to the very first tagged click in that journey. Last-click is the right default for short journeys; first-touch is better for long B2B cycles where the original touchpoint is months earlier than the conversion. Run both side by side and you'll see how different the answers can be.
Do I need to send revenue, or is a conversion count enough?
Send revenue. A signup worth $9/month and a signup worth $900/year both count as one conversion but represent a 100x difference in business value. The platform can do the rollups either way, but only if you pass the actual amount in the postback.
How does this work with privacy laws like GDPR?
Click ids and source/campaign tagging are first-party measurement — you're attributing clicks to your own marketing, not building cross-site profiles. That's lawful basis under legitimate interest in most jurisdictions, provided you don't pair it with PII without consent. Server-side conversion tracking is actually friendlier to consent regimes than browser pixels because you're not setting third-party cookies. The privacy line shifts when you start tying click ids to specific named individuals; the post on tracking links in email walks through where that line sits.
Sourcesshow citations
- ISO/IEC 18004:2015 — Information technology — Automatic identification and data capture techniques — QR Code bar code symbology specification. The formal QR standard underpinning every scan.
- Internet Engineering Task Force RFC 7234 — Hypertext Transfer Protocol (HTTP/1.1): Caching. The HTTP redirect and caching semantics behind a short link click.
- W3C — Beacon API specification. The standard for sending small server-side conversion events that survive page unload.
- MDN Web Docs — Document.cookie and Storage: setItem. First-party storage primitives for keeping click ids alive between landing and conversion.
- Stripe API documentation — Events and webhooks. The webhook shapes referenced for Shape-2 integrations (
checkout.session.completed,charge.refunded). - Branch — 2024 Mobile Attribution Survey. Source for the ~31% query-parameter loss rate on mobile clicks.
- Magazine Publishers Association — Print Magazine Consumption Studies, 2022-2024. Background data for print-channel attribution windows and reader behaviour.
Try it on your own domain
Branded short links and dynamic QR codes, on your subdomain or your own domain. One-time purchase, no per-click fees.