UTM Link Builder — PHP source
Build campaign tracking URLs with utm_source, utm_medium and utm_campaign parameters. Bulk mode processes a whole list, presets and import round-trip existing tracking URLs, and a validator flags attribution-breaking values — runs entirely in your browser.
This is the PHP implementation — the same logic the interactive tool runs, in a shareable, citable form.
<?php
/**
* utm-link-builder - campaign URL builder with canonical utm_* ordering.
*
* Display snippet: ports the core build($baseUrl, $params) from the
* TypeScript lib (src/lib/utm.ts). The lint/bulk/preset helpers live in
* the TypeScript/Go sources.
*
* Semantics: strip any stale utm_* params from the base URL, keep every
* unrelated query param in place, then append the given params in
* canonical order. Empty-string params are omitted. Returns null for an
* unparseable base. Standard library only.
*/
const CANONICAL = [
'source' => 'utm_source',
'medium' => 'utm_medium',
'campaign' => 'utm_campaign',
'term' => 'utm_term',
'content' => 'utm_content',
];
function build(string $baseUrl, array $params = []): ?string
{
if (strpos($baseUrl, '://') === false) {
$baseUrl = 'https://' . $baseUrl; // coerce a scheme-less host
}
$parts = parse_url($baseUrl);
if ($parts === false || !isset($parts['host'])) {
return null;
}
// Keep every unrelated query param; drop stale utm_* ones.
$kept = [];
foreach (explode('&', $parts['query'] ?? '') as $pair) {
if ($pair === '') {
continue;
}
$key = explode('=', $pair, 2)[0];
if (strpos($key, 'utm_') !== 0) {
$kept[] = $pair;
}
}
foreach (CANONICAL as $field => $queryKey) {
$value = $params[$field] ?? '';
if ($value !== '') {
$kept[] = $queryKey . '=' . rawurlencode($value);
}
}
$out = $parts['scheme'] . '://' . $parts['host'] . ($parts['path'] ?? '');
if ($kept !== []) {
$out .= '?' . implode('&', $kept);
}
if (isset($parts['fragment'])) {
$out .= '#' . $parts['fragment'];
}
return $out;
}
// Example:
// build('example.com/page?utm_source=stale&id=7', ['source' => 'twitter', 'medium' => 'social'])
// -> 'https://example.com/page?id=7&utm_source=twitter&utm_medium=social'
Also available in 13 other languages
Every CosmoDev tool ships its pure logic in TypeScript (web) and Go (CLI), with authored implementations in a dozen-plus languages — the same contract, ported. Compare all languages side by side →