Skip to content

Drop default UTM params from console CTAs - #8141

Merged
ankur-arch merged 5 commits into
mainfrom
drop-default-cta-utms
Aug 11, 2026
Merged

Drop default UTM params from console CTAs#8141
ankur-arch merged 5 commits into
mainfrom
drop-default-cta-utms

Conversation

@gregory-boch-prisma

@gregory-boch-prisma gregory-boch-prisma commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Why

The nav CTAs to console.prisma.io injected fallback UTMs (utm_source=website, utm_medium=<page slug>, utm_campaign=signup/login) whenever the visitor had no campaign params of their own. Since console and the website share the same PostHog project, this polluted attribution:

  • 2,284 of ~13.9k signups in the last 30 days (~16%) got $initial_utm_source permanently stamped as website — organic/direct visitors whose true first-touch is now masked forever.
  • 858 more signups had their last-touch utm_source overwritten to website.
  • utm_source=website is by far the largest non-null source on console pageviews (27.9k of ~150k in 14 days), dwarfing every real channel.

What changed

  • Removed the default UTM fallbacks in the site and blog NavigationWrappers — CTAs now carry UTMs only when the visitor's current URL actually has them.
  • Removed the utm_campaign=signup/login fallback in the shared WebNavigation console-href builder.
  • Kept the localStorage UTM persistence layer untouched: real campaign UTMs still pass through on landing and are re-injected (including first_utm_*) on console link clicks from later pages.

Verified locally

  • Clean visit → https://console.prisma.io/sign-up with no params.
  • Visit with ?utm_source=twitter&utm_medium=paid&utm_campaign=launch → CTAs carry those exact params.
  • After navigating to a clean page and clicking the CTA → persistence rewrites the link with stored last-touch + first_utm_* params.

Also included: page-level CTAs

The studio, postgres, ORM, and pricing pages had the same defaults hardcoded as literal query strings (utm_source=website&utm_medium=<page>&utm_campaign=cta) on their console links — dropped those too, and removed the defaultUtm prop from the unused ConsoleCtaButton. The pris.ly CTA shortlinks are now replaced with direct URLs too (confirmed with the pris.ly owner): pris.ly/pdp -> console.prisma.io/sign-up on the homepage, compute, and blog CTAs, and the compute pricing/docs/blog shortlinks -> their real prisma.io destinations. Direct console links let the persistence layer inject real campaign attribution at click time, which the external shortener host bypassed. Footer social shortlinks (pris.ly/github etc.) carry no UTMs and are untouched.

Heads-up for dashboards

After deploy, UTM-less console signups will have no utm_source instead of website. Reports keying on $initial_utm_source will show this segment as null/organic; anything filtering utm_source = 'website' will see that bucket drain. Existing persons' stamped values are unchanged.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Navigation and Console links no longer add default campaign parameters.
    • Tracking parameters are preserved only when explicitly present in the URL.
    • Console links across ORM, Postgres, pricing, Studio, homepage, blog, and Compute pages now use direct destinations.
    • Updated navigation and calls to action for more consistent link behavior.
  • Improvements

    • Login and signup actions now include more accurate click tracking.
    • Security policies now support images from Google Tag Manager.

The nav CTAs injected fallback UTMs (utm_source=website,
utm_medium=<page>, utm_campaign=signup/login) for visitors without
campaign params, permanently stamping ~16% of monthly signups'
first-touch attribution as "website" and masking their true
organic/direct origin. Real campaign UTMs still pass through, and
the localStorage persistence layer keeps injecting stored first/last
touch attribution on console link clicks.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
blog Ready Ready Preview Aug 11, 2026 8:38am
docs Ready Ready Preview Aug 11, 2026 8:38am
eclipse Ready Ready Preview Aug 11, 2026 8:38am
site Ready Ready Preview Aug 11, 2026 8:38am

Request Review

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 0a68abd8-6ce8-4585-9e8a-efc66ff1065b

📥 Commits

Reviewing files that changed from the base of the PR and between 24ee6f5 and 05d6ba0.

📒 Files selected for processing (11)
  • apps/blog/next.config.mjs
  • apps/docs/next.config.mjs
  • apps/site/next.config.mjs
  • apps/site/src/app/(index)/page.tsx
  • apps/site/src/app/compute/page.tsx
  • apps/site/src/app/postgres/page.tsx
  • apps/site/src/app/pricing/page.tsx
  • apps/site/src/app/pricing/pricing-hero-plans.tsx
  • apps/site/src/app/studio/page.tsx
  • packages/ui/src/components/navigation-menu.tsx
  • packages/ui/src/components/web-navigation.tsx

Walkthrough

The change removes default UTM propagation from blog and site navigation. Console CTAs now preserve explicit query parameters and record CTA clicks. Direct links use untracked destinations. A site development launch configuration runs on port 3106.

Changes

Navigation and CTA tracking

Layer / File(s) Summary
Remove default UTM propagation
apps/blog/src/app/(blog)/layout.tsx, apps/blog/src/components/navigation-wrapper.tsx, apps/site/src/app/layout.tsx, apps/site/src/components/navigation-wrapper.tsx, apps/site/src/components/console-cta-button.tsx
Navigation wrappers and Console CTAs no longer construct default UTM values. They pass exact query parameters or undefined.
Remove automatic campaign parameter and track navigation CTAs
packages/ui/src/components/web-navigation.tsx, packages/ui/src/components/navigation-menu.tsx
Console URL construction no longer adds utm_campaign. Desktop and mobile login and signup links now call trackCTA with CTA metadata.
Use direct Console and content destinations
apps/site/src/app/orm/page.tsx, apps/site/src/app/postgres/page.tsx, apps/site/src/app/pricing/page.tsx, apps/site/src/app/pricing/pricing-hero-plans.tsx, apps/site/src/app/studio/page.tsx, apps/blog/src/components/BlogCTA.tsx, apps/site/src/app/(index)/page.tsx, apps/site/src/app/compute/page.tsx
Console CTAs use ConsoleCtaButton or direct untracked URLs. Compute pricing, announcement, and documentation links use direct Prisma URLs.
Update analytics CSP allowlists
apps/blog/next.config.mjs, apps/docs/next.config.mjs, apps/site/next.config.mjs
The img-src policy allows images from Google Tag Manager.

Site development launch

Layer / File(s) Summary
Add site launch configuration
.claude/launch.json
Adds a pnpm launch configuration for the site Next.js development server on port 3106.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • prisma/web#8097: Both PRs modify UTM propagation logic used by navigation and Console links.

Suggested reviewers: amanvarshney01

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: removing default UTM parameters from console CTAs.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch drop-default-cta-utms

Comment @coderabbitai help to get the list of available commands.

@argos-ci

argos-ci Bot commented Aug 10, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Argos notifications ↗︎

Build Status Details Updated (UTC)
default (Inspect) ✅ No changes detected - Aug 11, 2026, 8:45 AM

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/ui/src/components/web-navigation.tsx (1)

80-81: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Add regression coverage for the new console URL contract.

When utm is absent, assert that both login and signup links have no query string. When utm contains exact utm_* values, assert that both links preserve them and do not add utm_campaign unless it was supplied.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ui/src/components/web-navigation.tsx` around lines 80 - 81, Add
regression tests around the link generation in the web navigation component,
covering absent utm and exact utm_* inputs. Assert loginHref and signupHref omit
the query string when utm is absent, preserve supplied UTM values unchanged, and
do not add utm_campaign unless explicitly provided.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/ui/src/components/web-navigation.tsx`:
- Around line 80-81: Add regression tests around the link generation in the web
navigation component, covering absent utm and exact utm_* inputs. Assert
loginHref and signupHref omit the query string when utm is absent, preserve
supplied UTM values unchanged, and do not add utm_campaign unless explicitly
provided.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 9a8d1161-905c-4bb6-aa5e-75df8b541943

📥 Commits

Reviewing files that changed from the base of the PR and between 6335674 and f263bb7.

📒 Files selected for processing (6)
  • .claude/launch.json
  • apps/blog/src/app/(blog)/layout.tsx
  • apps/blog/src/components/navigation-wrapper.tsx
  • apps/site/src/app/layout.tsx
  • apps/site/src/components/navigation-wrapper.tsx
  • packages/ui/src/components/web-navigation.tsx

coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 10, 2026
Same fix as the nav: the studio, postgres, orm, and pricing pages had
utm_source=website literals baked into their console links, stamping
organic visitors' attribution. The persistence layer still injects
real campaign UTMs at click time. Also removed the defaultUtm prop
from the unused ConsoleCtaButton.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 10, 2026
Per the pris.ly owner, the hero and compute CTAs now link directly:
pdp -> console.prisma.io/sign-up, and the compute pricing/docs/blog
shortlinks -> their real prisma.io destinations. Direct console links
let the UTM persistence layer inject real campaign attribution at
click time, which the external shortener host bypassed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
coderabbitai[bot]
coderabbitai Bot previously approved these changes Aug 10, 2026
The cta_click GA4 event (and its Google Ads conversion import) only
fired from the blog's CTA, while the actual site nav Login/Get started
buttons and the homepage/compute/pricing/postgres/studio hero and
body CTAs linked straight to console.prisma.io with no tracking at
all. The other GA4-imported conversion action, cta_click_auto, fires
on every link click sitewide and is too noisy to be a useful signal.

Also adds https://www.googletagmanager.com to img-src, which GTM's
own container diagnostics flagged as Urgent ("likely impacting
measurement") across 61 pages.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
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.

2 participants