UTM Link Builder — C# 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 C# implementation — the same logic the interactive tool runs, in a shareable, citable form.
// utm-link-builder — campaign URL builder with canonical utm_* ordering. Language: C# (.NET 7+, BCL only). Port of src/lib/utm.ts build(); lint/bulk/preset helpers live in the TypeScript/Go sources.
using System;
using System.Collections.Generic;
using System.Web;
static class UtmLinkBuilder
{
private static readonly (string Field, string QueryKey)[] Canonical =
{
("source", "utm_source"), ("medium", "utm_medium"), ("campaign", "utm_campaign"),
("term", "utm_term"), ("content", "utm_content"),
};
static string Build(string baseUrl, Dictionary<string, string> parameters)
{
string text = baseUrl.Contains("://") ? baseUrl : "https://" + baseUrl; // coerce scheme-less
if (!Uri.TryCreate(text, UriKind.Absolute, out var uri) || string.IsNullOrEmpty(uri.Host))
return null; // unparseable base
// ParseQueryString keeps pair order; remove stale utm_* entries.
var kept = HttpUtility.ParseQueryString(uri.Query);
foreach (var key in kept.AllKeys)
if (key != null && key.StartsWith("utm_", StringComparison.Ordinal))
kept.Remove(key);
foreach (var (field, queryKey) in Canonical)
{
if (!parameters.TryGetValue(field, out var value)) continue;
if (!string.IsNullOrEmpty(value)) kept[queryKey] = value;
}
var builder = new UriBuilder(uri) { Query = kept.ToString() };
return builder.Uri.ToString();
}
}
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 →