gistmax. Back to DiscoverStudio
Technology

Digital marketing tutorial: create campaign links you can audit

By Gistmax Tutorials · 2026-11-04

Digital marketing tutorial workflow: Choose labels, Build URL, Test landing, Record campaign.
Digital marketing tutorial workflow: Choose labels, Build URL, Test landing, Record campaign.

Campaign links become difficult to analyse when every person invents a different spelling for the same channel. Build a tiny link generator with a naming convention, then check that it preserves an existing query string and page fragment. This lesson creates URLs only; it does not install tracking or transmit visitor data.

1. Choose the naming convention

Imagine promoting a Gistmax technology tutorial through a newsletter. Use `newsletter` as the source, `email` as the medium and `tech_tutorials_nov` as the campaign. Keep the convention in a shared sheet so future links use the same names.

Do not put a subscriber's name, phone number or email address in campaign parameters. URLs can be copied, logged and shared. Parameters should describe the campaign, not identify the reader.

2. Build the URL with Python

You need Python 3.12 or later. Save this program as `campaign_links.py`. It uses the standard library, so no package installation is necessary.

from urllib.parse import urlsplit, urlunsplit, parse_qsl, urlencode

def campaign_url(base, source, medium, campaign):
    parts = urlsplit(base)
    if parts.scheme != "https" or not parts.netloc:
        raise ValueError("Use a complete HTTPS destination")
    tags = {
        "utm_source": source.strip().lower(),
        "utm_medium": medium.strip().lower(),
        "utm_campaign": campaign.strip().lower(),
    }
    if not all(tags.values()):
        raise ValueError("All campaign labels are required")
    # Replace existing campaign tags but preserve unrelated parameters.
    query = [(k, v) for k, v in parse_qsl(parts.query, keep_blank_values=True)
             if k not in tags]
    query.extend(tags.items())
    return urlunsplit((parts.scheme, parts.netloc, parts.path,
                      urlencode(query), parts.fragment))

link = campaign_url(
    "https://www.gistmax.com/?story=101#read",
    "Newsletter", "Email", "Tech_Tutorials_Nov"
)
print(link)
tags = dict(parse_qsl(urlsplit(link).query))
assert tags["story"] == "101"
assert tags["utm_source"] == "newsletter"
assert urlsplit(link).fragment == "read"

3. Test the destination before distribution

Run `python campaign_links.py`. The result should retain `story=101`, add three campaign parameters and keep `#read` at the end. Replace the example story ID with a published story that actually exists on your site, then open the generated URL in a browser.

Check both the page and the analytics configuration. Adding parameters to a URL does not, by itself, produce a report. Your chosen analytics service must be configured to collect the relevant visit information, subject to your site's consent and privacy settings.

4. Keep an audit sheet

Record the destination, campaign name, publishing channel, date and person responsible. When reviewing results, compare links from the same campaign window rather than mixing a one-day promotion with a month-long newsletter placement.

For a useful extension, generate links from a CSV containing source and medium columns. Reject empty labels and duplicate campaign names before exporting the finished URLs. That turns a one-off helper into a repeatable publishing check.

Troubleshooting

If the landing page disappears, check that the generator preserved its original query parameters. If a campaign is split across several rows in analytics, compare spelling and capitalisation. Never fix historical reporting by silently relabelling unrelated campaigns as if they were one experiment.

References

Python URL parsing and encoding · Google Analytics campaign URL guidance

Join the conversation →