## TL;DR
UTM tags must be stable per campaign; regenerating them per link creates dozens of fake campaigns. Centralize tag generation in one builder, backfill the canonical tags, and stop every other code path from minting its own.

```text
agent regenerated utm tags on every link and split all campaign attribution
```

## Use this when
- One campaign appears as dozens of utm_campaign variants.
- Attribution reports show traffic you cannot explain.
- An agent's link builder generates fresh tags per render.

## Not for this skill when
- Missing UTMs entirely, which is a tagging-coverage problem.
- Cross-device user stitching.
- Ad-platform click IDs, which are separate from UTMs.

## Steps
1. Query analytics for distinct UTM variants per campaign to measure the fragmentation. Verify: you have the count of variants for the worst campaign.
2. Define the canonical tag set for each active campaign. Verify: the mapping is written down and reviewed.
3. Replace the agent's per-link generation with a single UTM builder function. Verify: every link in the app flows through the builder.
4. Backfill or alias the fragmented variants to the canonical campaign in reports. Verify: the campaign's numbers consolidate.
5. Add a test that asserts tag stability: same campaign in, same tags out. Verify: the test fails if anyone reintroduces per-link generation.

## Variant phrasings
### utm tags different every link attribution
Common phrasing of the problem.
### utm_campaign fragmented variants analytics
The analytics-angle search.
### canonical utm tags builder
The fix-angle search.

Compatibility: Google Analytics, PostHog, Mixpanel, any UTM-consuming analytics; the tagging contract is universal.

## Why it happens
Analytics groups sessions by exact UTM strings, so 'launch', 'Launch', and 'launch_2' are three different campaigns. An agent that mints fresh tags per link or per render fragments every report and makes real performance unreadable.

## Edge cases / pitfalls
- Case differences fragment too; lowercase everything at the builder.
- UTMs on internal links overwrite the original campaign; strip them on internal navigation.
- Backfilling history is approximate; freeze the date the canonical tags took effect.
- Paid platforms add their own click IDs; keep those separate from your UTM scheme.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_LMMhFTK1q0Pwq2lX3BzRoA
