utm-link-generator ยท diff
git:20260410.ab060dd to git:20260608.d82d20f
22 added, 407 removed. Audit A to A.
---
name: utm-link-generator
description: Generates properly tagged UTM links with consistent naming conventions. Maintains a UTM registry file (utm-registry.json) to enforce naming consistency, prevent duplicates, generate short links, and output ready-to-copy links for LinkedIn, email, social, and ads.
tools: Read, Write, Bash
user_invocable: true
---
# UTM Link Generator
- A disciplined UTM link generation system that enforces consistent naming conventions across all campaigns, maintains a registry to prevent duplicates and naming drift, and outputs platform-ready links. This is not a simple URL concatenator -- it is a naming governance system for marketing attribution.
+ Generate UTM-tagged links under a single naming-governance system: a `utm-registry.json` that enforces canonical conventions, prevents duplicates and naming drift, and outputs platform-ready links for LinkedIn, email, social, and ads.
- ## Why This Exists
+ ## Contents
- UTM chaos is the number one cause of broken marketing attribution. When team members use "linkedin" vs "LinkedIn" vs "linked-in" vs "li" as a source, your analytics become useless. This skill enforces a single source of truth: the UTM registry.
+ - `references/naming-conventions.md` -- enforced rules, UTM parameter reference, canonical source/medium lists, campaign naming pattern.
+ - `references/platform-variants.md` -- per-platform link templates (LinkedIn, email, social, paid ads).
+ - `references/registry-schema.md` -- utm-registry.json structure plus validation-report and output-summary templates.
+ - `references/bulk-and-registry-ops.md` -- bulk generation, registry commands (audit/add/report/export), error handling, integrations, best practices.
## Capabilities
- 1. **Generate UTM-tagged URLs** with validated, consistent parameters
- 2. **Maintain a utm-registry.json** file that tracks all generated links and enforces naming conventions
- 3. **Prevent duplicates** -- warns when a similar link already exists in the registry
- 4. **Platform-specific formatting** -- outputs links optimized for LinkedIn, email, social, and ad platforms
- 5. **Bulk generation** -- create multiple variants for A/B testing or multi-channel campaigns
- 6. **Validation** -- rejects malformed URLs, empty parameters, and convention violations
- 7. **Reporting** -- generates campaign tracking summaries from the registry
-
- ## UTM Parameter Reference
-
- | Parameter | Required | Purpose | Example |
- |-----------|----------|---------|---------|
- | `utm_source` | Yes | Where the traffic comes from | `linkedin`, `google`, `newsletter` |
- | `utm_medium` | Yes | Marketing medium | `cpc`, `email`, `social`, `organic` |
- | `utm_campaign` | Yes | Campaign identifier | `q1-2026-product-launch` |
- | `utm_term` | No | Paid keyword (search ads) | `project-management-software` |
- | `utm_content` | No | Differentiates similar links | `hero-cta`, `sidebar-banner`, `variant-a` |
- | `utm_id` | No | Campaign ID for GA4 | `camp-2026-q1-001` |
-
- ## Naming Conventions (Enforced)
-
- These conventions are non-negotiable. The skill will reject or auto-correct any violations.
-
- ### General Rules
-
- 1. **All lowercase** -- Never `LinkedIn`, always `linkedin`
- 2. **Hyphens for spaces** -- Never `product launch`, always `product-launch`
- 3. **No special characters** -- Only alphanumeric and hyphens
- 4. **No trailing/leading hyphens** -- Never `-campaign-name-`
- 5. **No double hyphens** -- Never `my--campaign`
- 6. **Maximum length**: 50 characters per parameter value
- 7. **Date format in campaigns**: `q[N]-[YYYY]` or `[YYYY]-[MM]` prefix
-
- ### Source Values (Canonical List)
-
- Only these source values are allowed. Any new source must be explicitly added to the registry.
-
- | Canonical Source | Aliases (auto-corrected) | Platform |
- |-----------------|-------------------------|----------|
- | `google` | `goog`, `google-ads`, `adwords` | Google Ads / Organic |
- | `linkedin` | `li`, `linked-in`, `linkedin-ads` | LinkedIn |
- | `facebook` | `fb`, `meta`, `facebook-ads` | Facebook / Meta |
- | `instagram` | `ig`, `insta` | Instagram |
- | `twitter` | `x`, `x-com`, `tw` | X (Twitter) |
- | `youtube` | `yt`, `you-tube` | YouTube |
- | `tiktok` | `tt`, `tik-tok` | TikTok |
- | `reddit` | `rd` | Reddit |
- | `email` | `mail`, `e-mail`, `em` | Email campaigns |
- | `newsletter` | `nl`, `news-letter` | Newsletter specifically |
- | `bing` | `microsoft-ads`, `msn` | Bing / Microsoft |
- | `direct` | `none`, `(direct)` | Direct traffic |
- | `referral` | `ref`, `partner` | Referral traffic |
- | `podcast` | `pod`, `spotify` | Podcast channels |
- | `slack` | `sl` | Slack communities |
- | `producthunt` | `ph`, `product-hunt` | Product Hunt |
- | `hackernews` | `hn`, `hacker-news` | Hacker News |
-
- ### Medium Values (Canonical List)
-
- | Canonical Medium | Aliases (auto-corrected) | Use Case |
- |-----------------|-------------------------|----------|
- | `cpc` | `ppc`, `paid-click`, `cost-per-click` | Paid search / paid social clicks |
- | `cpm` | `display`, `paid-impression` | Display / impression campaigns |
- | `email` | `e-mail`, `mail` | Email campaigns |
- | `social` | `social-media`, `organic-social` | Organic social posts |
- | `organic` | `seo`, `organic-search` | Organic search traffic |
- | `referral` | `ref`, `partner`, `affiliate` | Referral / partner links |
- | `video` | `vid`, `youtube`, `pre-roll` | Video ad placements |
- | `retargeting` | `remarketing`, `retarget` | Retargeting campaigns |
- | `content` | `blog`, `article`, `content-syndication` | Content marketing |
- | `webinar` | `web`, `event`, `virtual-event` | Webinar / event registrations |
- | `podcast` | `pod`, `audio` | Podcast mentions / ads |
- | `sms` | `text`, `mms` | SMS / text campaigns |
- | `qr` | `qr-code`, `print` | QR code / print materials |
- | `push` | `push-notification`, `notification` | Push notifications |
-
- ### Campaign Naming Pattern
-
- Campaigns follow this structure:
-
- ```
- [quarter-or-month]-[year]-[campaign-name]-[optional-variant]
- ```
-
- Examples:
- - `q1-2026-product-launch`
- - `2026-03-spring-webinar`
- - `q2-2026-brand-awareness-linkedin`
- - `evergreen-demo-request` (for always-on campaigns, skip the date prefix)
-
- ## Execution Protocol
-
- ### Step 1: Accept Input
-
- The user provides some or all of these:
-
- - **Destination URL** (required) -- The page they want to link to
- - **Source** (required) -- Where the traffic comes from
- - **Medium** (required) -- The marketing channel type
- - **Campaign** (required) -- Campaign name
- - **Term** (optional) -- Keyword for paid search
- - **Content** (optional) -- Link differentiator
- - **Platforms** (optional) -- Which platforms to generate links for (default: all relevant)
-
- If the user provides a brief like "I need links for our Q1 product launch campaign on LinkedIn and email pointing to our pricing page," extract the parameters from natural language.
-
- ### Step 2: Validate and Normalize
-
- For each parameter:
-
- 1. **Convert to lowercase** -- `LinkedIn` becomes `linkedin`
- 2. **Replace spaces with hyphens** -- `product launch` becomes `product-launch`
- 3. **Strip special characters** -- Remove anything not `[a-z0-9-]`
- 4. **Check against canonical lists** -- Auto-correct known aliases (e.g., `fb` to `facebook`)
- 5. **Reject unknown values** -- If a source or medium is not in the canonical list and is not a reasonable addition, warn the user and suggest the closest match
- 6. **Validate URL** -- Ensure the destination URL is well-formed (has protocol, valid domain)
- 7. **Check length** -- Ensure no parameter exceeds 50 characters
-
- Report any corrections made:
- ```
- ## Parameter Validation
-
- - Source: "LinkedIn" -> "linkedin" (normalized to lowercase)
- - Medium: "paid" -> "cpc" (corrected to canonical value)
- - Campaign: "Q1 Product Launch!" -> "q1-product-launch" (normalized)
- - URL: https://example.com/pricing -- Valid
- ```
-
- ### Step 3: Check Registry for Duplicates
-
- Read the utm-registry.json file (or create it if it does not exist). Check for:
-
- 1. **Exact duplicates** -- Same URL + same parameters. Warn and return the existing link.
- 2. **Near duplicates** -- Same URL + same campaign + different content/medium. Warn but allow (this is often intentional for multi-channel tracking).
- 3. **Naming conflicts** -- Same campaign name but different capitalization or hyphenation. Block and show the existing convention.
-
- ### Step 4: Generate Links
-
- Build the UTM-tagged URL:
-
- ```
- {base_url}?utm_source={source}&utm_medium={medium}&utm_campaign={campaign}[&utm_term={term}][&utm_content={content}][&utm_id={id}]
- ```
-
- Rules:
- - If the base URL already has query parameters, append with `&` not `?`
- - URL-encode any parameter values that contain special characters
- - Preserve the base URL's existing query parameters and fragment
-
- ### Step 5: Generate Platform-Specific Variants
-
- For each platform requested, generate an optimized link:
-
- #### LinkedIn
-
- ```
- ## LinkedIn
-
- **Post Link** (organic social):
- https://example.com/pricing?utm_source=linkedin&utm_medium=social&utm_campaign=q1-2026-product-launch&utm_content=organic-post
-
- **Ad Link** (paid):
- https://example.com/pricing?utm_source=linkedin&utm_medium=cpc&utm_campaign=q1-2026-product-launch&utm_content=sponsored-post
-
- **Message Link** (InMail/DM):
- https://example.com/pricing?utm_source=linkedin&utm_medium=social&utm_campaign=q1-2026-product-launch&utm_content=inmail
-
- **Profile Link** (bio/featured):
- https://example.com/pricing?utm_source=linkedin&utm_medium=social&utm_campaign=q1-2026-product-launch&utm_content=profile-link
- ```
-
- #### Email
-
- ```
- ## Email
-
- **Primary CTA**:
- https://example.com/pricing?utm_source=email&utm_medium=email&utm_campaign=q1-2026-product-launch&utm_content=primary-cta
-
- **Secondary CTA**:
- https://example.com/pricing?utm_source=email&utm_medium=email&utm_campaign=q1-2026-product-launch&utm_content=secondary-cta
-
- **Header Link**:
- https://example.com/pricing?utm_source=email&utm_medium=email&utm_campaign=q1-2026-product-launch&utm_content=header-link
-
- **Footer Link**:
- https://example.com/pricing?utm_source=email&utm_medium=email&utm_campaign=q1-2026-product-launch&utm_content=footer-link
- ```
-
- #### Social (General)
-
- ```
- ## Social
-
- **Twitter/X**:
- https://example.com/pricing?utm_source=twitter&utm_medium=social&utm_campaign=q1-2026-product-launch
-
- **Facebook**:
- https://example.com/pricing?utm_source=facebook&utm_medium=social&utm_campaign=q1-2026-product-launch
-
- **Instagram** (bio link):
- https://example.com/pricing?utm_source=instagram&utm_medium=social&utm_campaign=q1-2026-product-launch&utm_content=bio-link
-
- **Reddit**:
- https://example.com/pricing?utm_source=reddit&utm_medium=social&utm_campaign=q1-2026-product-launch
- ```
-
- #### Ads (Paid)
-
- ```
- ## Paid Ads
-
- **Google Ads**:
- https://example.com/pricing?utm_source=google&utm_medium=cpc&utm_campaign=q1-2026-product-launch&utm_term={keyword}
-
- **LinkedIn Ads**:
- https://example.com/pricing?utm_source=linkedin&utm_medium=cpc&utm_campaign=q1-2026-product-launch
-
- **Facebook/Meta Ads**:
- https://example.com/pricing?utm_source=facebook&utm_medium=cpc&utm_campaign=q1-2026-product-launch
-
- Note: For Google Ads, use {keyword} as a dynamic placeholder that Google will auto-replace.
- ```
-
- ### Step 6: Update Registry
-
- Append all generated links to utm-registry.json:
-
- ```json
- {
- "version": "1.0",
- "lastUpdated": "2026-04-10T12:00:00Z",
- "namingConventions": {
- "sources": ["google", "linkedin", "facebook", "instagram", "twitter", "email", "newsletter"],
- "mediums": ["cpc", "cpm", "email", "social", "organic", "referral", "video", "retargeting"]
- },
- "campaigns": [
- {
- "name": "q1-2026-product-launch",
- "createdAt": "2026-04-10T12:00:00Z",
- "description": "Q1 2026 product launch campaign",
- "links": [
- {
- "id": "utm-001",
- "url": "https://example.com/pricing?utm_source=linkedin&utm_medium=social&utm_campaign=q1-2026-product-launch&utm_content=organic-post",
- "source": "linkedin",
- "medium": "social",
- "campaign": "q1-2026-product-launch",
- "content": "organic-post",
- "platform": "linkedin",
- "variant": "organic-post",
- "createdAt": "2026-04-10T12:00:00Z",
- "status": "active"
- }
- ]
- }
- ],
- "stats": {
- "totalLinks": 1,
- "totalCampaigns": 1,
- "sourcesUsed": ["linkedin"],
- "mediumsUsed": ["social"]
- }
- }
- ```
-
- ### Step 7: Output Summary
-
- Present the final output in a clean, copy-paste-ready format:
-
- ```
- ## UTM Links Generated
-
- **Campaign**: q1-2026-product-launch
- **Destination**: https://example.com/pricing
- **Generated**: 2026-04-10
-
- ### Ready-to-Copy Links
-
- | Platform | Variant | Link |
- |----------|---------|------|
- | LinkedIn (organic) | organic-post | [full URL] |
- | LinkedIn (paid) | sponsored-post | [full URL] |
- | Email (primary CTA) | primary-cta | [full URL] |
- | Email (secondary CTA) | secondary-cta | [full URL] |
- | Twitter | default | [full URL] |
- | Facebook | default | [full URL] |
-
- ### Registry Updated
- - New links added: 6
- - Total links in registry: 6
- - Registry file: ./utm-registry.json
-
- ### Validation Report
- - All parameters normalized to convention
- - No duplicate links found
- - No naming conflicts detected
- ```
-
- ## Bulk Generation Mode
-
- For generating links across many campaigns or many URLs at once.
-
- ### Input Format (Bulk)
-
- The user can provide a table or list:
-
- ```
- Generate UTM links for these pages:
- - /pricing -- linkedin, email, twitter -- q1-2026-product-launch
- - /demo -- linkedin, google-ads -- q1-2026-demo-push
- - /case-studies -- email, linkedin -- q1-2026-social-proof
- ```
-
- ### Processing
-
- 1. Parse each line into (URL, platforms, campaign)
- 2. Validate and normalize all parameters
- 3. Generate all variant links for each URL/platform combination
- 4. Deduplicate across the batch
- 5. Update registry with all new links
- 6. Output a master table
-
- ### Output Format (Bulk)
-
- ```
- ## Bulk UTM Generation -- 3 campaigns, 8 platform variants, 24 total links
-
- | Campaign | URL | Platform | Variant | Full Link |
- |----------|-----|----------|---------|-----------|
- | q1-2026-product-launch | /pricing | linkedin-organic | organic-post | [URL] |
- | q1-2026-product-launch | /pricing | linkedin-paid | sponsored-post | [URL] |
- | q1-2026-product-launch | /pricing | email | primary-cta | [URL] |
- | ... | ... | ... | ... | ... |
-
- Registry updated: 24 new links added.
- ```
-
- ## Registry Management Commands
-
- The user can also invoke this skill for registry operations:
-
- ### Audit Registry
-
- ```
- "Audit my UTM registry"
- ```
-
- Reads utm-registry.json and reports:
- - Total campaigns and links
- - Naming convention violations (if any crept in manually)
- - Stale campaigns (older than 6 months with no new links)
- - Unused sources or mediums
- - Duplicate or near-duplicate links
-
- ### Add Custom Source/Medium
-
- ```
- "Add 'partnerstack' as a UTM source"
- ```
-
- Adds the new value to the canonical list in the registry and documents it.
-
- ### Campaign Report
-
- ```
- "Show me all links for the q1-2026-product-launch campaign"
- ```
-
- Filters the registry and displays all links for that campaign, grouped by platform.
-
- ### Export for Google Sheets
-
- ```
- "Export my UTM registry as CSV"
- ```
-
- Generates a CSV file with columns: Campaign, URL, Source, Medium, Content, Term, Full Link, Created Date, Status.
-
- ## Error Handling
-
- | Error | Response |
- |-------|----------|
- | Invalid URL (no protocol) | Auto-prepend `https://` and warn |
- | Unknown source | Suggest closest canonical match, ask for confirmation |
- | Unknown medium | Suggest closest canonical match, ask for confirmation |
- | Campaign name too long | Suggest abbreviated version |
- | Duplicate link exists | Show existing link, ask if user wants to create anyway |
- | Registry file missing | Create new registry with default conventions |
- | Registry file corrupted | Attempt to parse what exists, back up, create fresh |
- | Base URL has existing UTMs | Strip existing UTM params, warn user, apply new ones |
-
- ## Integration Notes
+ 1. Generate UTM-tagged URLs with validated, consistent parameters.
+ 2. Maintain `utm-registry.json` tracking all links and enforcing conventions.
+ 3. Prevent duplicates -- warn when a similar link already exists.
+ 4. Format platform-specific variants (LinkedIn, email, social, ads).
+ 5. Bulk-generate variants for A/B testing or multi-channel campaigns.
+ 6. Validate -- reject malformed URLs, empty parameters, and convention violations.
+ 7. Report -- generate campaign tracking summaries from the registry.
- - **Google Analytics 4**: All parameters map directly to GA4 dimensions. utm_id maps to campaign_id.
- - **HubSpot**: Source and medium map to HubSpot's Original Source properties.
- - **Salesforce**: Campaign name can map to Salesforce Campaign records via integration.
- - **Mixpanel / Amplitude**: UTM params auto-captured on page load via standard SDKs.
+ ## Workflow
- ## Best Practices Embedded in This Skill
+ 1. **Accept input.** Collect destination URL, source, medium, campaign (all required) plus optional term, content, and target platforms. Extract these from a natural-language brief when not given explicitly.
+ 2. **Validate and normalize.** Lowercase, replace spaces with hyphens, strip non-`[a-z0-9-]` characters, auto-correct known aliases, reject unknown source/medium values (suggest closest match), validate URL form, enforce the 50-character limit. Report corrections using the template in `references/registry-schema.md`. Full rules in `references/naming-conventions.md`.
+ 3. **Check registry for duplicates.** Read `utm-registry.json` (create if missing). Return existing link on exact duplicates, allow-with-warning on near duplicates, block on naming conflicts (same campaign, different casing/hyphenation).
+ 4. **Generate links.** Build `{base_url}?utm_source=&utm_medium=&utm_campaign=[&utm_term=][&utm_content=][&utm_id=]`. Append with `&` if the base URL already has query params, URL-encode values, and preserve existing query params and fragment.
+ 5. **Generate platform variants.** Produce optimized links per requested platform using `references/platform-variants.md`.
+ 6. **Update registry.** Append all generated links to `utm-registry.json` per the schema in `references/registry-schema.md`, refreshing stats and timestamps.
+ 7. **Output summary.** Present a copy-paste-ready summary using the template in `references/registry-schema.md`.
- 1. **One registry, one truth** -- All UTM links flow through the registry. No ad-hoc link creation.
- 2. **Convention over configuration** -- Canonical lists prevent naming drift before it starts.
- 3. **Auto-correction over rejection** -- When possible, fix the input rather than blocking the user.
- 4. **Platform awareness** -- Different platforms need different utm_content values to distinguish placements.
- 5. **Date-prefixed campaigns** -- Makes it trivial to filter analytics by time period.
- 6. **Audit trail** -- Every link is timestamped and attributed in the registry.
+ For bulk runs, registry commands (audit, add source/medium, campaign report, CSV export), error handling, and integration notes, see `references/bulk-and-registry-ops.md`.