best-practicesUpdated 2025

URL Parameters Best Practices: Complete Guide 2024

Master URL parameter structure, naming, encoding, and validation. Best practices for bulletproof campaign tracking in GA4.

8 min readbest-practices

You're building campaign URLs for 2024. You want them to work perfectly in GA4, never break, and follow industry standards.

This is the complete best practices guide for URL parameters and UTM tracking.

🚨 Not sure what's breaking your tracking?

Run a free 60-second audit to check all 40+ ways UTM tracking can fail.

Scan Your Campaigns Free

✓ No credit card ✓ See results instantly

URL Parameter Structure (RFC 3986)

The Standard Format

Code
https://domain.com/path?key1=value1&key2=value2&key3=value3#fragment
                      ↑          ↑          ↑               ↑
                      ?          &          &               #

Rules:

  1. ONE question mark ? starts query string
  2. Ampersands & separate parameters
  3. Equal signs = connect keys to values
  4. Fragment # comes last (optional)
Code
?utm_source=`{"{"}{"{"}source{"}"}{"}"}}`&utm_medium=`{"{"}{"{"}medium{"}"}{"}"}}`&utm_campaign=`{"{"}{"{"}campaign{"}"}{"}"}}`&utm_content=`{"{"}{"{"}content{"}"}{"}"}}`&utm_term=`{"{"}{"{"}term{"}"}{"}"}}`

Why this order:

  • Source first (most important)
  • Medium second (channel)
  • Campaign third (specific initiative)
  • Content/Term last (optional details)

Naming Conventions

Use Lowercase Everything

Code
✅ CORRECT:
utm_source=facebook
utm_medium=cpc
utm_campaign=spring2024

❌ WRONG:
utm_source=Facebook  (breaks channel grouping)
utm_medium=CPC       (inconsistent)
utm_campaign=Spring2024  (mixed case)

Why: GA4 channel grouping is case-sensitive. "cpc" ≠ "CPC".

Use Hyphens or Underscores (Not Spaces)

Code
✅ CORRECT:
utm_campaign=spring-sale-2024
utm_campaign=spring_sale_2024

❌ WRONG:
utm_campaign=spring sale 2024  (breaks URL)
utm_campaign=spring%20sale%202024  (hard to read)

Choose one style and be consistent.

Keep It Short

Code
❌ TOO LONG (82 chars):
utm_campaign=2024-Q1-spring-collection-launch-womens-running-shoes-category-special-promotion

✅ BETTER (32 chars):
utm_campaign=2024-Q1-spring-womens

Reasons:

  • GA4 has 420-char URL limit
  • Shorter URLs are easier to share
  • Less error-prone
  • Better user experience

😰 Is this your only tracking issue?

This is just 1 of 40+ ways UTM tracking breaks. Most marketing teams have 8-12 critical issues they don't know about.

• 94% of sites have UTM errors

• Average: $8,400/month in wasted ad spend

• Fix time: 15 minutes with our report

✓ Connects directly to GA4 (read-only, secure)

✓ Scans 90 days of data in 2 minutes

✓ Prioritizes issues by revenue impact

✓ Shows exact sessions affected

Get Your Free Audit Report

URL Encoding Rules

When to Encode

Always encode:

  • Spaces → %20
  • Ampersands → %26
  • Question marks → %3F
  • Hash symbols → %23
  • Percent signs → %25
  • Plus signs → %2B

Example:

Code
Raw: utm_campaign=50% off sale
Encoded: utm_campaign=50%25%20off%20sale

When NOT to Encode

Don't encode:

  • Hyphens -
  • Underscores _
  • Periods .
  • Alphanumeric characters

Example:

Code
✅ CORRECT (no encoding needed):
utm_campaign=spring-2024_v1.0

❌ OVER-ENCODED:
utm_campaign=spring%2D2024%5Fv1%2E0

JavaScript Encoding

Javascript
// Use encodeURIComponent for parameter values
const campaign = '50% off sale';
const encoded = encodeURIComponent(campaign);
// Result: "50%25%20off%20sale"
 
// Full URL building
function buildCampaignUrl(base, source, medium, campaign) {
    const params = new URLSearchParams({
        utm_source: source,
        utm_medium: medium,
        utm_campaign: campaign
    });
    return `${"{"}{"{"}base{"}"}{"}"}}?${params.toString()}`;
}
 
// Usage
const url = buildCampaignUrl(
    'https://shop.com/products',
    'facebook',
    'cpc',
    '50% off sale'
);
// Result: https://shop.com/products?utm_source=facebook&utm_medium=cpc&utm_campaign=50%25+off+sale

Parameter Order and Structure

Start with ? (Question Mark)

Code
✅ CORRECT:
domain.com/page?utm_source=x

❌ WRONG:
domain.com/page&utm_source=x  (missing ?)
domain.com/pageutm_source=x   (no separator)

Use & (Ampersand) Between Parameters

Code
✅ CORRECT:
?utm_source=x&utm_medium=y&utm_campaign=z

❌ WRONG:
?utm_source=x?utm_medium=y  (double ?)
?utm_source=x,utm_medium=y  (comma separator)

Fragment Comes Last

Code
✅ CORRECT:
domain.com/page?utm_source=x&utm_medium=y#section

❌ WRONG:
domain.com/page#section?utm_source=x&utm_medium=y

Length Limits

GA4 Limit: 420 Characters

Code
Total URL length budget:
- Protocol:        8 chars  (https://)
- Domain:         20 chars  (average)
- Path:           50 chars  (average)
- UTM parameters: 150 chars (target)
- Buffer:         192 chars (for variations)
────────────────────────────────────────
TOTAL:           420 chars (GA4 max)
Code
utm_source:    max 15 chars
utm_medium:    max 15 chars
utm_campaign:  max 30 chars
utm_content:   max 20 chars
utm_term:      max 20 chars

Validation Checklist

Pre-Launch Validation

Before launching ANY campaign:

Code
□ URL starts with https://
□ ONE question mark only
□ Parameters separated by &
□ All UTM parameters lowercase
□ No spaces (use hyphens or URL encoding)
□ Total length ≤ 420 characters
□ Fragment (#) comes last if used
□ All special characters URL-encoded
□ Tested in GA4 Real-Time
□ Campaign name follows naming convention

Automated Validation Function

Javascript
function validateCampaignUrl(url) {
    const errors = [];
 
    // Check 1: HTTPS
    if (!url.startsWith('https://')) {
        errors.push('Use HTTPS for security');
    }
 
    // Check 2: One question mark
    const qCount = (url.match(/\?/g) || []).length;
    if (qCount === 0) {
        errors.push('Missing question mark before parameters');
    } else if (qCount > 1) {
        errors.push(`Multiple question marks found (${"{"}{"{"}qCount{"}"}{"}"}})`);
    }
 
    // Check 3: Length
    if (url.length > 420) {
        errors.push(`URL too long (${url.length} chars, limit 420)`);
    }
 
    // Check 4: Fragment position
    const qPos = url.indexOf('?');
    const hashPos = url.indexOf('#');
    if (hashPos > 0 && qPos > 0 && hashPos < qPos) {
        errors.push('Fragment (#) must come after query string (?)');
    }
 
    // Check 5: Required parameters
    if (!url.includes('utm_source=')) {
        errors.push('Missing utm_source');
    }
    if (!url.includes('utm_medium=')) {
        errors.push('Missing utm_medium');
    }
    if (!url.includes('utm_campaign=')) {
        errors.push('Missing utm_campaign');
    }
 
    // Check 6: Spaces
    if (url.includes(' ')) {
        errors.push('URL contains unencoded spaces');
    }
 
    return {
        valid: errors.length === 0,
        errors
    };
}
 
// Usage
const result = validateCampaignUrl('https://shop.com/products?utm_source=facebook&utm_medium=cpc&utm_campaign=spring2024');
 
if (result.valid) {
    console.log('✅ URL is valid');
} else {
    console.error('❌ Validation errors:', result.errors);
}

Common Mistakes to Avoid

1. Uppercase in utm_medium

Code
❌ WRONG:
utm_medium=CPC  (won't match GA4 channel grouping)

✅ CORRECT:
utm_medium=cpc
Code
❌ WRONG:
<a href="/products?utm_source=navbar">Products</a>
(Overwrites original traffic source)

✅ CORRECT:
<a href="/products">Products</a>
(No UTMs on internal links)

3. Forgetting URL Encoding

Code
❌ WRONG:
utm_campaign=50% off

✅ CORRECT:
utm_campaign=50%25%20off

4. Inconsistent Naming

Code
❌ WRONG:
Campaign 1: utm_campaign=spring_2024
Campaign 2: utm_campaign=spring-2024
Campaign 3: utm_campaign=Spring2024

✅ CORRECT (consistent):
Campaign 1: utm_campaign=spring-2024-shoes
Campaign 2: utm_campaign=spring-2024-apparel
Campaign 3: utm_campaign=spring-2024-accessories

✅ Fixed this issue? Great! Now check the other 39...

You just fixed one tracking issue. But are your Google Ads doubling sessions? Is Facebook attribution broken? Are internal links overwriting campaigns?

Connects to GA4 (read-only, OAuth secured)

Scans 90 days of traffic in 2 minutes

Prioritizes by revenue impact

Free forever for monthly audits

Run Complete UTM Audit (Free Forever)

Join 2,847 marketers fixing their tracking daily

FAQ

Should I use hyphens or underscores?

Both work. Choose one and be consistent. Most teams use hyphens.

Do I need to encode hyphens and underscores?

No. These characters are safe in URLs and don't need encoding.

source, medium, campaign, content, term. But any order works—GA4 parses by key name, not position.

Can I add custom parameters alongside UTMs?

Yes. Add your own parameters: ?utm_source=x&custom_param=y. Just ensure they don't conflict with UTM names.

Should I use + or %20 for spaces?

Use %20. The + sign is ambiguous (it can mean either space or plus sign).

How do I handle multiple values for one parameter?

Use comma-separated values or create separate campaigns. Don't use multiple parameters with the same key.

Conclusion

URL Parameter Best Practices:

  1. Structure: ? first, & between parameters, # last
  2. Naming: Lowercase, hyphens/underscores, max 30 chars
  3. Encoding: Spaces as %20, special chars encoded
  4. Validation: Check length, syntax, encoding before launch
  5. Consistency: Document conventions, train team

Follow these standards, and your campaign URLs will work perfectly in GA4 every time.


Technical Reference: Multiple Question Marks Validation Rule

UTM

Get Your Free Audit in 60 Seconds

Connect GA4, run the scan, and see exactly where tracking is leaking budget. No credit card required.

Trusted by growth teams and agencies to keep attribution clean.