Skip to content

UTM Link Builder — Ruby 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 Ruby implementation — the same logic the interactive tool runs, in a shareable, citable form.

# utm-link-builder — campaign URL builder with canonical utm_* ordering. Language: Ruby (stdlib uri). Port of src/lib/utm.ts build(); lint/bulk/preset helpers live in the TypeScript/Go sources.

require "uri"

CANONICAL = {
  "source" => "utm_source", "medium" => "utm_medium", "campaign" => "utm_campaign",
  "term" => "utm_term", "content" => "utm_content",
}.freeze

def build(base_url, params = {})
  base_url = "https://#{base_url}" unless base_url.include?("://") # coerce scheme-less
  uri = URI.parse(base_url) rescue nil
  return nil if uri.nil? || uri.host.to_s.empty?

  # Keep every unrelated query param; drop stale utm_* ones.
  kept = URI.decode_www_form(uri.query.to_s).reject { |key, _| key.start_with?("utm_") }

  CANONICAL.each do |field, query_key|
    value = params[field] || params[field.to_sym]
    kept << [query_key, value] if value && !value.to_s.empty?
  end

  uri.query = kept.empty? ? nil : URI.encode_www_form(kept)
  uri.to_s
end

# 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 →