Every WordPress affiliate knows the move: install a link plugin, and it cloaks your ugly affiliate URLs into tidy /go/ links and counts the clicks. On Next.js, there's no plugin to install — you build the redirect yourself. That sounds like a downgrade. It isn't. It's about thirty lines of code, and in exchange you get something no WordPress plugin gives you: the click captured first-party, on your server, before it ever leaves for the merchant. For a business that lives or dies on measurement, that's not a chore — it's the whole point.
The three jobs, same as anywhere
An affiliate link has three jobs to do, exactly as in the WordPress version of this guide: cloak it (a clean, branded URL you can change in one place), count the click, and attribute it (know which page and position drove it). A plugin does the first two and stops at a total. On Next.js, one route handler does all three — and the third is where the value is.
The build: one route handler
Point your pages at /go/<slug> instead of the raw affiliate URL, then create a single dynamic route that looks up the destination, logs the click, and redirects. In the App Router (Next 15/16, where params is async):
// app/go/[slug]/route.ts
import { NextRequest, NextResponse } from "next/server";
import { links } from "@/lib/affiliate-links";
import { recordClick } from "@/lib/analytics";
export async function GET(
req: NextRequest,
{ params }: { params: Promise<{ slug: string }> }
) {
const { slug } = await params;
const target = links[slug];
// unknown slug: send them home rather than error
if (!target) return NextResponse.redirect(new URL("/", req.url), 302);
// capture the click first-party — do not await, so the redirect stays fast
recordClick({
slug,
from: req.headers.get("referer"),
ua: req.headers.get("user-agent"),
at: Date.now(),
});
return NextResponse.redirect(target, 302);
}
The link map is plain config you can edit in one place (or move to a database as it grows):
// lib/affiliate-links.ts
export const links: Record<string, string> = {
"dyson-tp09": "https://www.amazon.com/dp/B0XXXXXXXX?tag=yoursite-20",
"ninja-af101": "https://www.amazon.com/dp/B0YYYYYYYY?tag=yoursite-20",
};
That's cloaking (clean /go/ URLs), counting (every click flows through recordClick), and the redirect — done. Change a destination once in the map and every link across your site updates.
Why owning the redirect changes everything
Here's the part a plugin can't match. Because you wrote the handler, the click is yours — first-party, server-side, captured before the visitor leaves. Look at what recordClick already has access to: the referer tells you which page sent the click; you can pass the slug's position from the link itself; the timestamp gives you real-time. Send that to your own database or analytics and you can answer the question the network dashboard and the plugin counter never can — which page and which placement actually earn — which is the entire premise of revenue attribution and the affiliate analytics stack.
A WordPress plugin gives you a click total. This gives you a click record, first-party, that you control. That gap is the difference between knowing you got clicks and knowing where your money comes from.
Getting the details right
A few things worth doing properly:
- Keep your tracking tag on the destination. The route controls the path; the Amazon tracking ID (or network parameters) on the target URL is what actually attributes the sale. The redirect doesn't replace it.
- Handle unknown slugs. Redirect home or return a 404 rather than erroring — links rot, and a broken
/go/link shouldn't throw. - Don't block the redirect. Fire
recordClickwithoutawait(or use a queue) so logging never slows the hop to the merchant. - Keep it out of the index. The
/go/route is functional, not content — don't link to it from sitemaps, and disallow it in robots if you like. - Disclosure still applies. Cloaking a link doesn't remove the obligation to disclose — generate one with the disclosure tool.
Next.js vs WordPress, honestly
WordPress wins on convenience: a plugin is faster than writing code, and if you never need per-page attribution, it's enough. Next.js wins on control and measurement: you own the redirect, so you own the data, and the click record is as detailed as you care to make it. For an affiliate operator who treats the site as a business to be measured — which is the whole thesis of this hub — that ownership is worth the thirty lines. You're not missing a plugin; you're skipping the ceiling it would have put on your data.
Turn those click records into revenue: Clickolytics connects the clicks your redirect route captures to the commissions they earn, so per-page attribution becomes a number you can act on. See how it works →
Frequently asked questions
How do I cloak links without a plugin?
A dynamic route — app/go/[slug]/route.ts — that maps a slug to the real URL and 302-redirects. Link to /go/slug on your pages.
Why is this better than a plugin? You own the redirect, so you capture the click first-party (page, position, time) before it leaves — the attribution a plugin's counter can't give.
Does it hurt SEO?
No — internal /go/ links and a 302 to the merchant are standard; just keep the route out of your indexable content.
Do I still need my Amazon tag? Yes — the tag on the destination URL is what attributes the sale; the route only cloaks and counts.
Related reading
- Affiliate Link Management in WordPress — the same three jobs on the other stack.
- Revenue Attribution for Affiliates — what the first-party click record unlocks.
- Amazon Associates Tracking IDs — the tag your destination still needs.
- How to Track Affiliate Links — the methods, ranked.