Tool
Shortlink call and return URL builder
Build the provider API call and the signed return URL together, and catch the encoding mistakes that break completion tracking.
Shortlink providers shorten by API: you call their endpoint with your token and a destination, and they answer with JSON containing a short URL. The destination you send them is your own return address, which is how you find out the user came back.
The common mistake is to skip the call and glue the destination onto a base URL. That produces a link the provider has never heard of, so the completion never registers and the user earns nothing while your logs look fine.
This builds the call and the return URL together, and flags the things that quietly break one or the other.
- API call you make
- https://provider.example/api?api=YOUR_API_TOKEN&url=https%3A%2F%2Fyoursite.example%2Fr.php%3Ft%3Da1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6Destination percent-encoded. This is what nearly every provider expects.
- Return URL they send the user back to
- https://yoursite.example/r.php?t=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6
- What comes back
- {"status":"success","shortenedUrl":"https://…/abc"}send the user to that short URL — never to a hand-built one
// 1. Open a run and issue the token BEFORE calling the provider.
$token = bin2hex(random_bytes(16));
$pdo->prepare('UPDATE shortlink_runs SET status = "expired" WHERE user_id = ? AND status = "open"')
->execute([$userId]); // kills the ten-tabs trick
$pdo->prepare('INSERT INTO shortlink_runs (user_id, link_id, token, status, started_at)
VALUES (?, ?, ?, "open", NOW())')->execute([$userId, $linkId, $token]);
// 2. Ask the provider to shorten YOUR return URL.
$short = shorten($provider, 'https://yoursite.example/r.php?t=a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6');
// 3. Send the user to $short. They come back to r.php?t=… and you check
// ownership, single use, and minimum time away.Notes
The return URL has to be absolute and should be short. It passes through a third party, so keep anything sensitive out of it — the run token is a random id that means nothing on its own, which is the point.
Expire any run still open for that user when a new one starts. Without it, ten tabs produce ten completions from one pass through the provider.
Check the time away on return, and store the dwell minimum per provider rather than globally — their timers differ.
Never show the API call in an error message. It contains your token.