Skip to content

Expand UTM allowlists for paid LinkedIn + email campaigns#38

Merged
etagwerker merged 1 commit into
mainfrom
add-paid-social-utm-allowlist
May 22, 2026
Merged

Expand UTM allowlists for paid LinkedIn + email campaigns#38
etagwerker merged 1 commit into
mainfrom
add-paid-social-utm-allowlist

Conversation

@etagwerker
Copy link
Copy Markdown
Member

Summary

Expands UTM_SOURCES, UTM_MEDIUMS, and UTM_CAMPAIGN so paid LinkedIn ads and HubSpot/ConvertKit email broadcasts can be tracked through Librarian with accurate attribution. Today those campaigns either 422 on share creation or get lumped under utm_medium=Organic.

New values

Allowlist Added
UTM_SOURCES HubSpot
UTM_MEDIUMS CPC, Email, Newsletter, PaidSocial
UTM_CAMPAIGN LinkedIn-Roadmap-Test, LinkedIn-TLA, Newsletter, Rails-Upgrade-Guide, Re-engagement

Why these specifically

  • Paid LinkedIn: PaidSocial + CPC mediums, plus LinkedIn-TLA and LinkedIn-Roadmap-Test campaigns. Unblocks an in-flight Thought Leader Ad test promoting the Roadmap service against a matched-audiences company list.
  • HubSpot broadcasts: HubSpot source + Email medium, plus Rails-Upgrade-Guide (for list 187 sends) and Re-engagement (lapsed-subscriber sequences).
  • ConvertKit newsletter: Newsletter medium and Newsletter campaign so recurring sends are separable from one-off broadcasts.

Naming style question

Existing campaign values are single-word PascalCase (Upgraderuby, Blogpromo). The new values are hyphenated (LinkedIn-TLA, Rails-Upgrade-Guide, Re-engagement) because most new campaigns will be multi-word and hyphens read better in analytics dashboards. Happy to switch them to single-word style (LinkedinTla, RailsUpgradeGuide, Reengagement) if you'd rather keep the existing convention strictly.

Tests

Six new specs follow the same pattern as the Bluesky utm_source case added in #37. One per new value across mediums, campaigns, and the HubSpot source. bundle exec rspec spec/models/share_spec.rb -> 17 examples, 0 failures.

Test plan

  • CI passes
  • Spot-check that hitting POST /links/:id/shares.json with utm_medium=PaidSocial&utm_campaign=LinkedIn-TLA now returns 201 instead of 422
  • Confirm naming style preference before merge

🤖 Generated with Claude Code

Adds the values needed to track three classes of campaigns
that the marketing stack runs today but couldn't accurately
attribute through Librarian:

- Paid LinkedIn: PaidSocial, CPC mediums; LinkedIn-TLA,
  LinkedIn-Roadmap-Test campaigns. Unblocks an in-flight
  Thought Leader Ad test promoting the Roadmap service.
- HubSpot broadcasts: HubSpot source; Email medium;
  Rails-Upgrade-Guide and Re-engagement campaigns. Today
  these are tagged Organic which lumps them under organic
  social traffic in GA4.
- ConvertKit newsletter: Newsletter medium and Newsletter
  campaign so recurring sends are separable from one-off
  broadcasts.

A note on naming: existing campaign values are single-word
PascalCase (Upgraderuby, Blogpromo). The new values are
hyphenated (LinkedIn-TLA, Rails-Upgrade-Guide,
Re-engagement) because most new campaigns will be multi-
word and hyphens read better in analytics dashboards.
Happy to switch them to the existing single-word style if
you'd prefer (LinkedinTla, RailsUpgradeGuide, Reengagement).

Tests follow the same pattern as the Bluesky utm_source
case added in #37.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@etagwerker etagwerker merged commit cc951bc into main May 22, 2026
1 check passed
@etagwerker etagwerker deleted the add-paid-social-utm-allowlist branch May 22, 2026 21:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant