<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Paul</title>
    <description>The latest articles on DEV Community by Paul (@codetocash).</description>
    <link>https://dev.to/codetocash</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3888331%2Faab5b89c-bf1f-4812-868b-b351b90e7060.png</url>
      <title>DEV Community: Paul</title>
      <link>https://dev.to/codetocash</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/codetocash"/>
    <language>en</language>
    <item>
      <title>Conversion Tracking for Developers: From Zero to Full Funnel Visibility</title>
      <dc:creator>Paul</dc:creator>
      <pubDate>Sat, 20 Jun 2026 12:54:10 +0000</pubDate>
      <link>https://dev.to/codetocash/conversion-tracking-for-developers-from-zero-to-full-funnel-visibility-10pi</link>
      <guid>https://dev.to/codetocash/conversion-tracking-for-developers-from-zero-to-full-funnel-visibility-10pi</guid>
      <description>&lt;p&gt;You can't optimize what you don't measure. Every blog post about conversion optimization, A/B testing, or paid ads assumes you have reliable tracking in place. But most developers set up analytics as an afterthought — dropping a script on the page and calling it done. The result is data that's incomplete, untrustworthy, and ultimately useless for making decisions.&lt;/p&gt;

&lt;p&gt;This guide gives you a developer-first approach to conversion tracking. We'll cover event instrumentation, attribution setup, funnel visualization, and the specific tracking architecture you need to answer real business questions. No marketing jargon. No vague advice. Just the exact setup that turns your analytics from a vanity dashboard into a decision-making tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Tracking Mindset
&lt;/h2&gt;

&lt;p&gt;Before you write any code, understand what you're trying to learn. Tracking every possible event creates noise. Tracking the wrong events leads to wrong conclusions.&lt;/p&gt;

&lt;p&gt;Start with one question: "What are the 3-5 actions a user takes between discovering my product and paying me money?" Map these actions in order. That's your funnel. Every event you track should map directly to a step in that funnel.&lt;/p&gt;

&lt;p&gt;For a typical SaaS product, the funnel looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Discovery:&lt;/strong&gt; User visits your site from a traffic source&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Engagement:&lt;/strong&gt; User reads content, explores features, or uses a tool&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Intent:&lt;/strong&gt; User clicks "Sign Up" or "Start Trial"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conversion:&lt;/strong&gt; User completes signup and activates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Revenue:&lt;/strong&gt; User upgrades to a paid plan&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you track these five steps reliably, you can answer 90% of the marketing questions that matter: Which traffic source brings the most valuable users? Where do users drop off? What's my true cost per acquisition?&lt;/p&gt;

&lt;h2&gt;
  
  
  Event Instrumentation: What to Track and How
&lt;/h2&gt;

&lt;p&gt;Events are the atomic unit of conversion tracking. An event is any action a user takes that you want to measure. Let's build your event taxonomy from the ground up.&lt;/p&gt;

&lt;h3&gt;
  
  
  Foundational Events (Track These First)
&lt;/h3&gt;

&lt;p&gt;These four events are non-negotiable. Set them up before you do anything else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Page View&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Track every page load with the URL, referrer, and UTM parameters. This gives you baseline traffic data and attribution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Example with Plausible&lt;/span&gt;
&lt;span class="nf"&gt;plausible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pageview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;u&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Example with PostHog&lt;/span&gt;
&lt;span class="nx"&gt;posthog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$pageview&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;$current_url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;href&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;$referrer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;referrer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;utm_source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utm_source&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;utm_medium&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utm_medium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;utm_campaign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utm_campaign&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Sign Up Started&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Fire this event when a user clicks your primary signup CTA — not when they submit the form. The click indicates intent. The form submission indicates completion. You need both to measure form abandonment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[data-event="signup-started"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;posthog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sign_up_started&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;cta_text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerText&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Sign Up Completed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Fire this when the user successfully creates an account. Include the signup method (email, OAuth provider) and any UTM parameters from the original session.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;posthog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sign_up_completed&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;utm_source&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utm_source&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="na"&gt;time_to_complete&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;signup_start_time&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Subscription Created&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Fire this when a user successfully pays you money. Include the plan name, amount, currency, and billing interval. This is your revenue event.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;posthog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;capture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;subscription_created&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pro&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;USD&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;interval&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;month&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;trial_conversion&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// if converting from trial&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Engagement Events (Track These Next)
&lt;/h3&gt;

&lt;p&gt;Once your foundational events are reliable, add events that measure product engagement. These help you understand which features drive conversion.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feature Usage Events.&lt;/strong&gt; Track the core actions in your product. For a deployment tool: "first_deployment." For an API: "first_api_call." For a code formatter: "first_file_formatted." These events map to your product's aha moment.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Upgrade Prompt Events.&lt;/strong&gt; Track when users see an upgrade prompt and whether they click it. This tells you if your upgrade triggers are well-timed or annoying.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Support Events.&lt;/strong&gt; Track when users visit your docs, open your help widget, or contact support. High support interaction before signup often indicates confusion in your onboarding.&lt;/p&gt;

&lt;h3&gt;
  
  
  Events You Should NOT Track
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Mouse movements and scroll depth.&lt;/strong&gt; These create massive event volumes without actionable insight. If you need scroll data, track it as a single "scrolled_to_75%" event, not a continuous stream.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Every button click.&lt;/strong&gt; Track CTA clicks and conversion actions. Don't track "user clicked the footer logo." That data never changes a decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server errors as user events.&lt;/strong&gt; 500 errors belong in your error tracking tool (Sentry, LogRocket), not your analytics. The exception: track "payment_failed" as a conversion event because it directly impacts revenue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attribution: Understanding Where Users Come From
&lt;/h2&gt;

&lt;p&gt;Attribution is how you connect a conversion to the marketing channel that caused it. Get this wrong and you'll optimize for the wrong channels.&lt;/p&gt;

&lt;h3&gt;
  
  
  First-Touch vs. Last-Touch Attribution
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;First-touch attribution&lt;/strong&gt; gives credit to the channel that brought the user to your site for the first time. Use this to answer: "Which channels are best at generating awareness?"&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Last-touch attribution&lt;/strong&gt; gives credit to the channel the user interacted with immediately before converting. Use this to answer: "Which channels are best at closing the deal?"&lt;/p&gt;

&lt;p&gt;Example: A user discovers your tool through a Twitter post (first touch), reads your blog via search two days later (middle touch), and clicks a link in your newsletter to sign up (last touch).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First-touch attribution credits Twitter for the signup&lt;/li&gt;
&lt;li&gt;Last-touch attribution credits the newsletter for the signup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither is wrong. They answer different questions. First-touch tells you where to invest in awareness. Last-touch tells you where to invest in conversion.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up UTM Parameters
&lt;/h3&gt;

&lt;p&gt;UTM parameters are the standard way to tag links for attribution. Every external link you control should include them.&lt;/p&gt;

&lt;p&gt;Use this exact structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;utm_source&lt;/code&gt;: The platform (twitter, google, newsletter, producthunt)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;utm_medium&lt;/code&gt;: The format (social, organic, email, cpc, referral)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;utm_campaign&lt;/code&gt;: The specific initiative (launch-week, black-friday, onboarding-email-3)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;utm_content&lt;/code&gt;: Optional — use for A/B testing (button-a, button-b)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example URL: &lt;code&gt;https://yoursite.com/?utm_source=twitter&amp;amp;utm_medium=social&amp;amp;utm_campaign=plg-guide&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Store UTM parameters in sessionStorage when the user first lands. Pass them through to your signup event so you know which campaign drove the conversion even if the user signs up days later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utm_source&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utm_medium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utm_campaign&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utm_content&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;sessionStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The "How Did You Hear About Us" Field
&lt;/h3&gt;

&lt;p&gt;UTM parameters miss a huge chunk of traffic: word of mouth, dark social (private Slack channels, Discord servers), and direct navigation. Capture this with a simple dropdown during signup.&lt;/p&gt;

&lt;p&gt;Keep the options specific but limited:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Search Engine (Google, DuckDuckGo, etc.)&lt;/li&gt;
&lt;li&gt;Twitter / X&lt;/li&gt;
&lt;li&gt;Reddit&lt;/li&gt;
&lt;li&gt;LinkedIn&lt;/li&gt;
&lt;li&gt;Friend or Colleague&lt;/li&gt;
&lt;li&gt;Blog Post or Newsletter&lt;/li&gt;
&lt;li&gt;Product Hunt&lt;/li&gt;
&lt;li&gt;Other&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't make this field required — it adds friction. But make it visible and easy to select. The data quality will surprise you. Most SaaS founders discover that "Friend or Colleague" is their largest acquisition channel and they had no idea.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Your Conversion Funnel
&lt;/h2&gt;

&lt;p&gt;A funnel is just a sequence of events where each step is a subset of the previous step. Your analytics tool can build this automatically once your events are instrumented.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Standard SaaS Funnel
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;th&gt;Typical Drop-Off&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Site Visit&lt;/td&gt;
&lt;td&gt;pageview&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Signup Started&lt;/td&gt;
&lt;td&gt;sign_up_started&lt;/td&gt;
&lt;td&gt;60-70%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Signup Completed&lt;/td&gt;
&lt;td&gt;sign_up_completed&lt;/td&gt;
&lt;td&gt;30-40%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Product Activated&lt;/td&gt;
&lt;td&gt;feature_used_core&lt;/td&gt;
&lt;td&gt;40-50%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trial Converted&lt;/td&gt;
&lt;td&gt;subscription_created&lt;/td&gt;
&lt;td&gt;15-25%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;If your drop-off at any step is significantly worse than these benchmarks, that's your optimization priority.&lt;/p&gt;

&lt;h3&gt;
  
  
  Funnel Analysis in Practice
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Calculate step-by-step conversion rates.&lt;/strong&gt; Don't just look at overall conversion (visit → paid). Look at each transition. A low visit-to-signup rate indicates a landing page problem. A low signup-to-activation rate indicates an onboarding problem. A low activation-to-paid rate indicates a product value problem.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Segment by traffic source.&lt;/strong&gt; Your overall funnel might look healthy, but one channel could be dragging it down. Maybe Twitter traffic converts at 5% but Reddit traffic converts at 0.5%. That tells you to invest more in Twitter and either fix your Reddit landing page or stop posting there.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Segment by cohort.&lt;/strong&gt; Compare users who signed up this week vs. last month. If conversion rates are dropping, something broke — a landing page change, a pricing change, or a product bug.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Measure time between steps.&lt;/strong&gt; How long does it take from signup to activation? From activation to payment? Long delays indicate friction. If users take 14 days to activate on average, but your trial is only 7 days, you've found your problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Privacy and Compliance
&lt;/h2&gt;

&lt;p&gt;Conversion tracking doesn't require invasive data collection. Here's how to track responsibly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Don't use third-party cookies.&lt;/strong&gt; First-party cookies and localStorage are sufficient for session tracking and attribution. Third-party cookies create privacy risk without meaningful analytics benefit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Anonymize IP addresses.&lt;/strong&gt; Most privacy-focused analytics tools do this by default. If you're using a self-hosted solution, configure it to drop the last octet of IP addresses before storage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Respect Do Not Track.&lt;/strong&gt; Check &lt;code&gt;navigator.doNotTrack&lt;/code&gt; and skip tracking entirely if the user has opted out. This is legally required in some jurisdictions and ethically required everywhere.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Store data in the user's region.&lt;/strong&gt; If you serve EU users, ensure your analytics data is stored in the EU or use a tool that's GDPR-compliant by design (Plausible, Fathom).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Be transparent in your privacy policy.&lt;/strong&gt; List exactly what you track, why you track it, and how long you retain it. Developer audiences particularly appreciate this transparency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools and Setup
&lt;/h2&gt;

&lt;p&gt;You don't need an expensive analytics stack. Here's the minimal viable setup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Privacy-focused web analytics:&lt;/strong&gt; Plausible ($9/month) or Fathom ($14/month). Both give you pageviews, referrers, and UTM tracking without cookies or complex configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product analytics:&lt;/strong&gt; PostHog (generous free tier) or Amplitude (free tier available). These handle event tracking, funnel analysis, and cohort reporting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Revenue tracking:&lt;/strong&gt; Your payment processor (Stripe, Paddle) already tracks revenue. Connect it to your product analytics via webhook or API to correlate revenue with user behavior.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Error tracking:&lt;/strong&gt; Sentry (free tier) for technical errors. Don't mix error data with analytics data, but do track "payment_failed" and "signup_error" as analytics events.&lt;/p&gt;

&lt;h3&gt;
  
  
  One-Day Setup Checklist
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install Plausible or PostHog on your site&lt;/li&gt;
&lt;li&gt;Add the four foundational events (pageview, signup started, signup completed, subscription created)&lt;/li&gt;
&lt;li&gt;Add UTM parameter capture to sessionStorage&lt;/li&gt;
&lt;li&gt;Add the "How did you hear about us" dropdown to your signup form&lt;/li&gt;
&lt;li&gt;Create a funnel report: pageview → signup started → signup completed → subscription created&lt;/li&gt;
&lt;li&gt;Set up a weekly email report of top traffic sources and conversion rates&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This entire setup takes less than a day and gives you more actionable data than 90% of SaaS companies have.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reading Your Data Correctly
&lt;/h2&gt;

&lt;p&gt;Collecting data is easy. Drawing the right conclusions is hard. Here are the most common mistakes developers make when interpreting analytics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Correlation vs. causation.&lt;/strong&gt; Just because users who read your blog convert at 8% doesn't mean the blog caused the conversion. Maybe blog readers are already warmer leads. To prove causation, run an A/B test or compare cohorts with matched characteristics.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Survivorship bias.&lt;/strong&gt; If you analyze only users who completed signup, you'll miss the reasons people dropped off. Study the failures, not just the successes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vanity metrics.&lt;/strong&gt; Page views and total signups feel good but don't pay bills. Focus on revenue per visitor, trial-to-paid conversion rate, and customer lifetime value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Over-optimization.&lt;/strong&gt; A 1% improvement in conversion rate matters when you have 10,000 visitors per month. It doesn't matter when you have 100. Focus on traffic acquisition and product value before you obsess over marginal conversion gains.&lt;/p&gt;

&lt;p&gt;Once your tracking is reliable, the &lt;a href="https://codetocash.dev/blog/ab-testing-landing-page-guide" rel="noopener noreferrer"&gt;A/B testing guide&lt;/a&gt; shows you how to run experiments that improve conversion rates with statistical confidence. If you want to understand how acquisition costs fit into your funnel economics, the &lt;a href="https://codetocash.dev/blog/customer-acquisition-cost-saas" rel="noopener noreferrer"&gt;customer acquisition cost guide&lt;/a&gt; breaks down the math. And for the complete marketing framework that ties tracking, testing, and optimization together, read the &lt;a href="https://codetocash.dev/drm-101" rel="noopener noreferrer"&gt;DRM 101 guide&lt;/a&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://codetocash.dev/blog/conversion-tracking-developers" rel="noopener noreferrer"&gt;CodeToCash.dev&lt;/a&gt;. I'm building it in public — documenting the journey from zero to profitable.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
