Campaign Link Validation — The Complete Guide
Campaign link validation is the practice of programmatically checking every campaign URL before it goes live — confirming that the destination resolves, the SSL certificate is valid, redirect chains don't strip your UTM parameters, and the landing page is ready for social sharing. Done right, validation is a single command that runs in seconds and catches the problems that cost marketing teams clicks, attribution data, and budget. This guide covers everything: what to check, why, how to do it from the terminal, how to automate it in CI/CD, and how to wire it into an AI agent workflow.
What is campaign link validation?
Campaign link validation is a pre-publish quality check that runs against every URL you plan to share in a marketing campaign. Instead of manually clicking a link and hoping it works, validation programmatically verifies a checklist of technical requirements: the URL resolves with a 200 status, HTTPS is configured, redirect chains preserve your UTM parameters, and the landing page has the Open Graph and Twitter Card meta tags required for rich social previews.
Think of it as the marketing equivalent of a compiler check. You wouldn't ship code without verifying it compiles. You shouldn't publish a campaign link without verifying it passes a validation suite. The difference is that campaign link failures are invisible until after you've spent money — a 404 page, a stripped UTM parameter, or a missing og:image tag won't throw a runtime error. It will silently drain your budget while your analytics data deteriorates.
The validation workflow has three stages:
- Build — generate a UTM-tagged URL with consistent, properly formatted parameters
- Check — verify the destination URL resolves correctly with SSL, no broken redirect chains, and acceptable response time
- Inspect — confirm the landing page is social-sharing-ready with OG tags, Twitter Cards, viewport meta, canonical URL, and favicon
MissingLinkz runs all three stages in a single mlz preflight command. The result is a structured JSON report with a top-level ready flag that tells you (and any AI agent in your workflow) whether the link is safe to publish.
Why marketing teams skip campaign link validation (and what it costs)
Most marketing teams skip validation for three reasons: they don't have a tool for it, they trust that someone else checked it, or they assume that if the URL looks right it probably works. All three are expensive assumptions.
- No dedicated tool
- The standard marketing toolkit doesn't include a link validator. Google's Campaign URL Builder generates UTM links but checks nothing. UTM builder dashboards store your parameters but don't verify the destination. So teams build links in one tool, manually test in a browser, and publish — hoping the landing page behaves the same way in production as it did during their one manual click.
- The "someone else checked it" assumption
- In multi-person marketing teams, no one person owns link validation. The copywriter assumes the developer set up the landing page correctly. The developer assumes QA tested the redirects. QA assumes someone else checked the social preview. The result is a campaign where everyone assumed validation happened and no one actually did it.
- The "it looks right" assumption
- A URL can look completely valid — HTTPS, no obvious typos, the right domain — and still fail in ways that are invisible to manual inspection. A page that loads in 4 seconds looks fine in a browser but kills 20% of your conversions. An
og:imagetag pointing to an image that returns 404 won't show up in your browser but will render a blank preview on LinkedIn. Redirect chains that strip UTM parameters look like normal redirects when you click them. Validation catches these because it tests programmatically, not just visually.
The cost of skipping validation is documented. According to research cited in how broken campaign links waste ad budget, broken attribution affects the majority of marketing campaigns. Missing OG images reduce social post click-through rates by 2–3x. A single second of extra page load time costs roughly 7% in conversions. These aren't edge cases — they're the default outcome when validation is optional.
The 9 things every campaign link should be checked for
Not all checks are equal in importance, but all of them have a real failure mode. Here is the complete list of what every campaign link needs before it publishes:
- 1. SSL / HTTPS
- The destination URL must use HTTPS. HTTP pages trigger browser security warnings that immediately erode trust. Paid traffic sent to an HTTP page is effectively wasted — most users bounce on sight of the "Not Secure" indicator. This is the simplest check and the most embarrassing to miss.
- 2. Resolution (HTTP status)
- The URL must respond with a
200 OK. Checks against 404 not-found, 301/302 redirects as the final destination, 500 server errors, and completely unreachable domains. A 404 in a campaign is particularly damaging for paid channels where you pay per click regardless of whether the page exists. - 3. Redirect chains
- Every redirect hop is an opportunity to lose your UTM parameters and add latency. The check traces the full redirect path from the initial URL to the final destination, flags chains longer than one hop, and verifies that UTM parameters survive each hop intact. This is the check that catches the most insidious attribution problem in marketing: silently stripped parameters that show up as "direct" traffic in GA4.
- 4. Response time
- Slow pages kill conversions. A threshold of 1.5 seconds triggers a warning; 3 seconds is a failure. This check uses actual HTTP response time, not simulated lab conditions, so it reflects what real users will experience when they click your campaign link.
- 5. Open Graph tags
- Checks for
og:title,og:description, andog:image. These three tags control how your link appears when shared on LinkedIn, Facebook, Slack, iMessage, and most other social surfaces. Missing any one of them degrades the preview quality. A missingog:imagein particular means your post renders as a plain URL — no image card, no visual hook, dramatically fewer clicks. See the complete guide to checking OG tags for details. - 6. Twitter Card tags
- Twitter/X uses its own meta tag system separate from Open Graph. Checks for
twitter:card,twitter:title, andtwitter:description. Without these tags, your link renders as plain text in the X feed regardless of how well-configured your OG tags are. - 7. Viewport meta tag
- Confirms the page includes
<meta name="viewport" content="width=device-width, initial-scale=1">. Pages without this tag render at desktop width on mobile devices, making them nearly unreadable. Given that over 60% of social traffic comes from mobile, a missing viewport tag is a conversion killer. - 8. Canonical URL
- Compares the page's
<link rel="canonical">value against the destination URL. A mismatch — for example, canonical pointing tohttps://example.com/landingwhile your campaign link useshttps://example.com/landing/— splits analytics data across two URLs and creates SEO confusion about which page to index. - 9. UTM parameter integrity
- Verifies that all required UTM parameters (
utm_source,utm_medium,utm_campaign) are present, properly formatted, lowercase, and free of special characters that can break tracking. Also verifies they survive the full redirect chain intact. For naming consistency guidelines, see the UTM naming convention guide.
Manual validation vs. automated validation
Manual validation means clicking the link, viewing source, using the Facebook Debugger, and inspecting the browser's network tab. It works, takes 5–10 minutes per link, and checks maybe 3 of the 9 items above reliably. It doesn't scale to 20 campaign links. It doesn't run in CI/CD. It doesn't fit into an AI agent workflow.
Automated validation runs all 9 checks programmatically in under 3 seconds per URL. It produces machine-readable output (structured JSON) that can be consumed by CI pipelines, agent workflows, Slack bots, or any other downstream tool. It's consistent: it runs the same checks every time, with the same thresholds, and produces comparable results across campaigns.
The table below shows which checks each approach can reliably cover:
| Check | Manual (browser) | Google URL Builder | Automated (mlz) |
|---|---|---|---|
| SSL / HTTPS | ✓ Visible | ✗ Not checked | ✓ Always |
| Resolution (200 OK) | ✓ Visible | ✗ Not checked | ✓ Always |
| Redirect chain / UTM preservation | ✗ Not visible | ✗ Not checked | ✓ Always |
| Response time | ≈ Approximate | ✗ Not checked | ✓ Precise |
| Open Graph tags | ≈ Via view-source | ✗ Not checked | ✓ Always |
| Twitter Card tags | ≈ Via view-source | ✗ Not checked | ✓ Always |
| Viewport meta | ✗ Not obvious | ✗ Not checked | ✓ Always |
| Canonical URL match | ✗ Not obvious | ✗ Not checked | ✓ Always |
| UTM parameter integrity | ≈ Partially | ≈ Partially | ✓ Always |
The most important column is "Redirect chain / UTM preservation." Manual inspection and URL builders both fail this check because neither one programmatically follows redirect chains to verify parameter survival. Automated validation does this by default on every run.
How to validate a campaign link from the terminal
The fastest way to run campaign link validation is with mlz preflight. Install once, then run against any URL.
npm install -g missinglinkz
Then run a preflight check against your campaign landing page:
mlz preflight --url "https://example.com/landing" --campaign "spring-launch" --source "linkedin" --medium "social"
The command builds the tracked URL, validates the destination, and inspects the landing page metadata. The JSON response looks like this:
{
"ready": true,
"tracked_url": "https://example.com/landing?utm_source=linkedin&utm_medium=social&utm_campaign=spring-launch",
"checks": [
{ "check": "og_tags", "status": "pass", "message": "All essential Open Graph tags present." },
{ "check": "twitter_card", "status": "pass", "message": "Twitter Card tags configured." },
{ "check": "viewport", "status": "pass", "message": "Viewport meta tag present." },
{ "check": "ssl", "status": "pass", "message": "URL uses HTTPS." },
{ "check": "resolution", "status": "pass", "message": "Destination responded with 200." }
],
"summary": { "total": 12, "passed": 12, "warnings": 0, "failed": 0 },
"recommendation": "All checks passed. Campaign link is ready to publish."
}
The ready: true flag is the single signal your workflow needs to proceed. When ready: false, the checks array lists exactly which checks failed and why — no guessing about what broke.
You can also run destination validation or metadata inspection independently if you want narrower checks:
mlz check "https://example.com/landing"
mlz inspect "https://example.com/landing"
mlz check runs the URL-level checks (SSL, resolution, redirects, response time). mlz inspect runs the metadata checks (OG tags, Twitter Card, viewport, canonical, favicon). mlz preflight runs both, plus builds and stores the UTM link.
How to validate campaign links in CI/CD
For teams that manage campaign links in a repository — config files, spreadsheets exported as JSON, or any structured list of URLs — validation belongs in CI/CD. Every time the campaign config changes, the pipeline validates all affected links and fails the build if any check doesn't pass.
This is particularly valuable for agencies and performance marketing teams who manage large numbers of links across multiple campaigns. See the full guide at automating campaign link validation in CI/CD for working GitHub Actions and GitLab CI examples. The short version: use --format json to get machine-readable output, then parse the ready field and exit with a non-zero code on failure:
RESULT=$(mlz preflight --url "$URL" --campaign "$CAMPAIGN" --source "$SOURCE" --medium "$MEDIUM" --format json)
echo "$RESULT" | jq -e '.ready == true'
The jq -e flag causes a non-zero exit when the expression evaluates to false or null, which is exactly what you want for a CI gate. If ready is false, the pipeline fails and no broken links ship to production.
How to validate campaign links from an AI agent
AI agents can't reliably use web-form UTM builders. They can't fill out GUI forms, they can't navigate multi-step web UIs, and they can't read visual feedback. What they can do is call tools that accept structured input and return structured output. That's exactly what the MissingLinkz MCP server provides.
Start the MCP server:
mlz mcp
Add it to your MCP client config (Claude Code, Cursor, Claude Desktop, or any MCP-compatible agent):
{
"mcpServers": {
"missinglinkz": {
"command": "mlz",
"args": ["mcp"]
}
}
}
Once connected, the agent can call mlz_preflight as a tool — passing the destination URL, UTM parameters, and post copy as structured arguments — and receive a JSON report with a ready verdict. The agent gets a clear go/no-go signal without touching a web form. For a full walkthrough of AI agent campaign link workflows, see why your AI agent can't use your UTM builder and how to build UTM links with an AI agent.
Common campaign link validation failures and how to fix them
These are the failures that show up most often when teams run validation for the first time:
- Missing
og:image - The most common failure. The landing page has
og:titleandog:descriptionbut noog:image. Fix: add a<meta property="og:image" content="https://yoursite.com/og-image.jpg">tag pointing to an image that is at least 1200×630 pixels. Use an absolute URL, not a relative path. After adding the tag, re-runmlz inspectto confirm it's detected, then clear the Facebook Debugger cache if you've already shared the URL. - UTM parameters stripped in redirect
- The URL resolves correctly but UTM parameters are missing from the final destination. This usually happens at a redirect from HTTP to HTTPS, from
wwwto non-www, or through a URL shortener. Fix: update the campaign URL to target the final destination directly (skip the redirect chain), or configure the redirect to preserve query strings. If you're using a URL shortener, verify it passes through query parameters by checking its documentation. - Slow response time (> 1.5s warning, > 3s failure)
- The page is slow to respond. This is a landing page performance problem, not a campaign link problem, but it still blocks a clean validation result. Fix: run a performance audit (Lighthouse, WebPageTest), address the largest contributors to load time (uncompressed images, render-blocking scripts, no CDN), and re-run validation. Don't publish a paid campaign to a page that's consistently above 3 seconds.
- Canonical URL mismatch
- The page's canonical tag points to a different URL than the one you're targeting. Often caused by a trailing slash discrepancy (
/landingvs/landing/) or a CMS that hardcodes canonical URLs. Fix: either update your campaign link to match the canonical exactly, or update the page's canonical tag to match your campaign URL. Both values should be identical. - Missing Twitter Card tags
- Open Graph tags are present but Twitter Card tags are absent. Twitter/X requires its own separate
twitter:cardmeta tag; OG tags are not automatically read by X. Fix: add at minimum<meta name="twitter:card" content="summary_large_image">along withtwitter:title,twitter:description, andtwitter:image. Use X's Card Validator tool to confirm after adding. - UTM parameter casing inconsistency
- Parameters contain uppercase letters (
utm_source=LinkedIninstead ofutm_source=linkedin). GA4 treats these as different values, which fragments your data. Fix: enforce lowercase across all UTM parameters. MissingLinkz does this automatically when you build withmlz buildormlz preflight. See the UTM naming convention guide for a complete taxonomy.
Frequently asked questions
- How is campaign link validation different from a link checker?
- A standard link checker only verifies that a URL resolves (returns 200 vs. 404). Campaign link validation goes further: it checks SSL, follows redirect chains while verifying UTM parameter preservation, measures response time, inspects Open Graph and Twitter Card meta tags, checks viewport and canonical configuration, and validates UTM parameter formatting. The output is a structured report with a clear go/no-go verdict, not just a status code.
- Do I need to validate every link in a campaign?
- Yes, if the links go to different destination URLs or use different UTM sources. If you're sending the same URL to three different platforms (LinkedIn, X, newsletter), run validation once per source/medium combination because each generates a different tracked URL. Validation for the same base destination URL is fast — under 3 seconds — so the overhead is minimal relative to the cost of publishing a broken link.
- Can validation catch a page that loads correctly in the browser but fails for some users?
- Validation catches server-side issues that affect all users: missing meta tags, HTTP status codes, SSL configuration, response time, and redirect chains. It doesn't emulate browser-side rendering or test JavaScript-dependent content. If your landing page's OG tags are dynamically injected by JavaScript rather than in the static HTML, validation won't see them — which is itself a problem, since most social media crawlers don't execute JavaScript either.
- How often should I validate campaign links?
- Before every campaign goes live, and again if the destination URL or landing page changes. If you're running automated campaigns from a pipeline, add validation as a pre-deploy step so any change to a campaign config triggers a fresh validation run. For high-budget campaigns, consider re-validating 24 hours after launch to catch issues that develop after go-live (expired certs, CDN misconfigurations, A/B test interference).
- Does MissingLinkz store my campaign links?
- Yes, when you're authenticated with an API key. The
mlz preflightcommand builds, validates, and stores the tracked URL so you can retrieve it later withmlz links list. For offline or unauthenticated use, UTM generation works without an API key but the link isn't stored. Free tier includes 50 links per month; paid plans start at $9/month for 2,000 links.
Related reading
Try campaign link validation now
Install MissingLinkz and validate your next campaign link before it goes live. One command checks everything.
npm install -g missinglinkz
mlz preflight --url "https://yoursite.com/landing" --campaign "your-campaign" --source "linkedin" --medium "social"