<?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>Forem: Joshua</title>
    <description>The latest articles on Forem by Joshua (@dubco_tips).</description>
    <link>https://forem.com/dubco_tips</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3818417%2F004a5ab7-ae00-4cc9-abac-61f6d177d5a1.jpg</url>
      <title>Forem: Joshua</title>
      <link>https://forem.com/dubco_tips</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/dubco_tips"/>
    <language>en</language>
    <item>
      <title>Stop Paying $35/Month for Bitly: A Developer's Guide to Free Alternatives</title>
      <dc:creator>Joshua</dc:creator>
      <pubDate>Tue, 24 Mar 2026 14:42:26 +0000</pubDate>
      <link>https://forem.com/dubco_tips/stop-paying-35month-for-bitly-a-developers-guide-to-free-alternatives-10ok</link>
      <guid>https://forem.com/dubco_tips/stop-paying-35month-for-bitly-a-developers-guide-to-free-alternatives-10ok</guid>
      <description>&lt;h1&gt;
  
  
  Stop Paying $35/Month for Bitly: A Developer's Guide to Free Alternatives
&lt;/h1&gt;

&lt;p&gt;I was staring at my Bitly invoice last week—$35 a month for link management—when I realized something ridiculous: I was paying premium prices for features I barely used, while free alternatives sitting right next to it had everything I actually needed.&lt;/p&gt;

&lt;p&gt;If you're a developer in the same boat, this one's for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bitly Problem
&lt;/h2&gt;

&lt;p&gt;Let's be honest: Bitly made sense in 2010. Your links were getting mangled by Twitter's character limit, and you needed &lt;em&gt;something&lt;/em&gt; to track clicks. But it's 2025, and we're still paying $35/month for what amounts to a URL shortener with basic analytics.&lt;/p&gt;

&lt;p&gt;Here's what that costs over time:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;$35/month = $420/year&lt;/li&gt;
&lt;li&gt;Over 5 years: $2,100&lt;/li&gt;
&lt;li&gt;Over a developer career: potentially thousands&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And for what? A branded link, some click analytics, and API access. Things that modern platforms—many of them completely free—now include as standard.&lt;/p&gt;

&lt;p&gt;I spent two weeks testing alternatives and found something that made Bitly's pricing look absurd. &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; does everything Bitly does at the $35/month tier, &lt;strong&gt;and they do it for free&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bitly vs. Dub.co: The Breakdown
&lt;/h2&gt;

&lt;p&gt;Let me show you exactly what you're overpaying for:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Bitly Free&lt;/th&gt;
&lt;th&gt;Bitly Pro ($35/mo)&lt;/th&gt;
&lt;th&gt;Dub.co Free&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Custom domain&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Link analytics&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API access&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QR codes&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team collaboration&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Click tracking&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branded QR codes&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Webhook support&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rate limits&lt;/td&gt;
&lt;td&gt;50/month&lt;/td&gt;
&lt;td&gt;Generous&lt;/td&gt;
&lt;td&gt;1,000/month&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;That's it.&lt;/strong&gt; Dub.co's free plan has everything in Bitly's $35/month tier. And if you're building something at scale, their paid plans start at $9/month for 50k links and full API access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Your First Link (It's Trivial)
&lt;/h2&gt;

&lt;p&gt;Here's how you create a shortened link with Dub.co's API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.dub.co/links &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "url": "https://example.com/super-long-blog-post-url",
    "domain": "yourdomain.com",
    "key": "myblog"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. You get back:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"shortLink"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://yourdomain.com/myblog"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/super-long-blog-post-url"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"clicks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"createdAt"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-03-24T10:30:00Z"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare that to Bitly, where you'd need to pay to even &lt;em&gt;have&lt;/em&gt; API access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Developer Example: Building a Link Tracker
&lt;/h2&gt;

&lt;p&gt;Let me show you why Dub.co's API is genuinely better for developers. Here's a quick Node.js script that creates link analytics dashboards:&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;axios&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createCampaignLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;campaignName&lt;/span&gt;&lt;span class="p"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.dub.co/links&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;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;links.example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;campaignName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;expiresAt&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;Date&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="mi"&gt;30&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// 30 days&lt;/span&gt;
    &lt;span class="na"&gt;tags&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;campaign&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;campaignName&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;span class="na"&gt;headers&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getClickStats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkId&lt;/span&gt;&lt;span class="p"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&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="s2"&gt;`https://api.dub.co/links/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;linkId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/analytics`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;headers&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &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;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createCampaignLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://blog.example.com/new-feature&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;product-launch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Link created: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shortLink&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Check stats after 24 hours&lt;/span&gt;
  &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &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;stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getClickStats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Clicks: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clicks&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Top referrer: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;topReferrer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&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;Bitly requires you to upgrade to even &lt;em&gt;access&lt;/em&gt; their API. Dub.co gives you this out of the box. Free.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Developer Experience Matters
&lt;/h2&gt;

&lt;p&gt;Here's what I noticed immediately after switching:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Webhooks&lt;/strong&gt;: Dub.co supports webhooks for click events. Real-time link analytics pushed to your app. Bitly's free tier? Doesn't have them. You're stuck polling their API.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Open Source&lt;/strong&gt;: Dub.co publishes their open-source clients on GitHub. You can see exactly how the library works, fork it, contribute. Bitly's API documentation feels like it was written in 2015 and never updated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Custom Domains&lt;/strong&gt;: Both offer this now, but Dub.co makes it frictionless. Add your domain, get CNAME validation instructions, done. Five minutes max. Bitly requires verification and waiting.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;QR Codes with Branding&lt;/strong&gt;: Dub.co generates branded QR codes automatically. Logo in the center, custom colors. No extra steps. It's the kind of polish that makes you realize why you were overpaying elsewhere.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Numbers: What I'm Actually Saving
&lt;/h2&gt;

&lt;p&gt;My setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;3 projects with branded short domains&lt;/li&gt;
&lt;li&gt;~200 links per month&lt;/li&gt;
&lt;li&gt;Basic analytics on each&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bitly&lt;/strong&gt;: $35/month × 12 = &lt;strong&gt;$420/year&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Dub.co&lt;/strong&gt;: Free (forever, unless I hit 10k links in a month, which I won't)&lt;/p&gt;

&lt;p&gt;I've been using Dub.co for 6 months. Total cost: &lt;strong&gt;$0&lt;/strong&gt;. I've saved $210 so far, and I honestly can't tell a functional difference from the $35/month Bitly plan.&lt;/p&gt;

&lt;h2&gt;
  
  
  Switching Is Painless
&lt;/h2&gt;

&lt;p&gt;Worried about migrating? Here's what takes 30 minutes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create your Dub.co account&lt;/li&gt;
&lt;li&gt;Add your custom domain(s)&lt;/li&gt;
&lt;li&gt;Update DNS records (just a CNAME)&lt;/li&gt;
&lt;li&gt;Bulk import old Bitly links if you care (optional—honestly, just start fresh)&lt;/li&gt;
&lt;li&gt;Update any hardcoded links in your code or docs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's genuinely it. Your old Bitly links keep working. Your new links go through Dub.co.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to Consider Paid Plans
&lt;/h2&gt;

&lt;p&gt;Dub.co's free plan handles most use cases, but if you're:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Running a link-heavy SaaS with 10k+ links/month&lt;/li&gt;
&lt;li&gt;Building a client-facing link management product&lt;/li&gt;
&lt;li&gt;Need advanced team controls and SSO&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...then their paid plans ($9-29/month) still beat Bitly's pricing by a huge margin.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Paying $35/month for Bitly in 2025 is like paying for a Nokia phone when iPhones exist and are free. &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; isn't new—they've been quietly building for years—but they finally have feature parity (and honestly, better features) than Bitly's paid tier.&lt;/p&gt;

&lt;p&gt;Try it free. Seriously. Create an account, play with the API, build a quick link tracker. If you hate it, you've lost nothing. If you love it (you will), you've just saved $420/year and gained a better developer experience.&lt;/p&gt;

&lt;p&gt;Your wallet will thank you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Start with Dub.co free →&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;




&lt;p&gt;Have you switched from Bitly? What tool are you using instead? Drop a comment—I'm curious what the community's landed on.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>tutorial</category>
      <category>tools</category>
    </item>
    <item>
      <title>Building a Link Management System for Your SaaS Product (Free Stack)</title>
      <dc:creator>Joshua</dc:creator>
      <pubDate>Mon, 23 Mar 2026 14:35:27 +0000</pubDate>
      <link>https://forem.com/dubco_tips/building-a-link-management-system-for-your-saas-product-free-stack-400d</link>
      <guid>https://forem.com/dubco_tips/building-a-link-management-system-for-your-saas-product-free-stack-400d</guid>
      <description>&lt;h1&gt;
  
  
  Building a Link Management System for Your SaaS Product (Free Stack)
&lt;/h1&gt;

&lt;p&gt;Every time you share a link to your SaaS product—whether it's in an email campaign, a social media post, or a landing page—you're missing data. How many clicks? Where are they from? What's your actual conversion rate from that specific channel?&lt;/p&gt;

&lt;p&gt;Most founders I talk to are still using links that look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://yourapp.com/?utm_source=email&amp;amp;utm_medium=campaign&amp;amp;utm_campaign=launch
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works, but it's unwieldy, unmeasurable across channels, and impossible to update once it's out there. If you realize your landing page is down, you can't fix the broken link—it's already in 500 emails.&lt;/p&gt;

&lt;p&gt;There's a better way. And no, you don't need to spend $35/month on Bitly anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Link Management Is Actually Important for SaaS
&lt;/h2&gt;

&lt;p&gt;Before I built my link management system, I treated links like a commodity. They either worked or they didn't. But once I started tracking them properly, I discovered some shocking gaps in my funnel:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Links from my newsletter were converting at 2x the rate of links from Twitter&lt;/li&gt;
&lt;li&gt;My referral link had a typo for three weeks (nobody clicked it)&lt;/li&gt;
&lt;li&gt;I was losing traffic because I had no way to update old links across multiple platforms&lt;/li&gt;
&lt;li&gt;My analytics dashboard couldn't show me which content formats drove actual signups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A proper link management system isn't about vanity metrics. It's about closing the gap between "I shared this" and "I know what happened."&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes a Good Link Management System?
&lt;/h2&gt;

&lt;p&gt;When I started evaluating solutions, I looked for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Custom domains&lt;/strong&gt; (branded links look more professional)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real-time analytics&lt;/strong&gt; (clicks, geographic data, referrer tracking)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;QR code generation&lt;/strong&gt; (increasingly important for offline→online conversion)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API access&lt;/strong&gt; (I wanted to integrate this into my product)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reusability&lt;/strong&gt; (I needed to update links without breaking existing shares)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team collaboration&lt;/strong&gt; (my co-founder needed access)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The big players—Bitly, TinyURL, custom link shorteners—either charged a fortune or locked features behind expensive plans.&lt;/p&gt;

&lt;p&gt;Then I found &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt;, and honestly, it felt like I'd been overpaying for years.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bitly Problem (And How Dub Solved It)
&lt;/h2&gt;

&lt;p&gt;Let me be blunt: Bitly charges $35/month for features that should be free.&lt;/p&gt;

&lt;p&gt;For context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bitly Pro&lt;/strong&gt;: $35/month — custom domain, API access, advanced analytics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bitly Enterprise&lt;/strong&gt;: Custom pricing (we're talking 4-figure contracts)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Meanwhile, &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; gives you all of that on the free plan. I'm not exaggerating.&lt;/p&gt;

&lt;p&gt;Here's what you actually get for free:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Dub.co Free&lt;/th&gt;
&lt;th&gt;Bitly Pro&lt;/th&gt;
&lt;th&gt;Bitly Enterprise&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Custom Domain&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API Access&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QR Codes&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Click Analytics&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team Members&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;td&gt;Up to 3&lt;/td&gt;
&lt;td&gt;Custom&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;$35/mo&lt;/td&gt;
&lt;td&gt;Custom&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The craziest part? Dub is open-source. If you want to self-host, you can. If you want to use their hosted version with analytics included, that's free too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building Your Link Management Workflow
&lt;/h2&gt;

&lt;p&gt;Here's how I set it up for my SaaS:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Create Your Link with the API
&lt;/h3&gt;

&lt;p&gt;Instead of manually creating links, I automated it using Dub's API. This is what my Node.js snippet looks like:&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;createLink&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;originalUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;campaign&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://api.dub.co/links&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="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&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="s2"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&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="s2"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;originalUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;links.yourapp.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Your custom domain&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;campaign&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// e.g., "launch-email-001"&lt;/span&gt;
      &lt;span class="na"&gt;expiresAt&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;Date&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="mi"&gt;90&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// 90 days&lt;/span&gt;
      &lt;span class="na"&gt;tags&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="s2"&gt;marketing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;campaign&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;campaign&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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_campaign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;campaign&lt;/span&gt;
    &lt;span class="p"&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;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shortUrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Returns links.yourapp.com/launch-email-001&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means every email I send generates a trackable link automatically. No manual work.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Track Performance in Real-Time
&lt;/h3&gt;

&lt;p&gt;Dub's analytics dashboard shows me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clicks per link (and when they happened)&lt;/li&gt;
&lt;li&gt;Geographic distribution&lt;/li&gt;
&lt;li&gt;Device type (mobile vs. desktop)&lt;/li&gt;
&lt;li&gt;Referrer (which tells me if someone shared my link)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I built a dashboard that pulls this data hourly:&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;getLinkAnalytics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkId&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`https://api.dub.co/links/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;linkId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/analytics?interval=1h`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&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="s2"&gt;Authorization&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Log to my internal analytics&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Link &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;linkId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; got &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clicks&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; clicks in the last hour`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Top countries: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;topCountries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&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;
  
  
  3. Use QR Codes for Offline-to-Online
&lt;/h3&gt;

&lt;p&gt;This was a game-changer for me. I printed QR codes on my business cards, product packaging, and in email signatures. Dub generates them instantly, with custom branding.&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;generateQRCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkKey&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="c1"&gt;// Dub generates QR automatically for every link&lt;/span&gt;
  &lt;span class="c1"&gt;// Access it at: https://api.dub.co/links/${linkId}/qr&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qrUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://qr.dub.co/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;linkKey&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Returns a PNG you can embed anywhere&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;qrUrl&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;h2&gt;
  
  
  Real Numbers: What Changed for Me
&lt;/h2&gt;

&lt;p&gt;After three months using &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Email conversion tracking&lt;/strong&gt;: I discovered my product-launch emails convert 2.8x better than my updates emails. I now send launches 2x per month (up from 1x).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Link rotation&lt;/strong&gt;: I updated a broken link in my bio once. Old shares still worked (I just redirected them). This was impossible before.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost savings&lt;/strong&gt;: Switching from Bitly saved me $35/month. Over a year, that's $420. For a early-stage SaaS, that money went to infrastructure instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Setup time&lt;/strong&gt;: Creating 50+ trackable links went from 30 minutes (manual Bitly clicks) to 30 seconds (API script).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why This Matters for SaaS Founders
&lt;/h2&gt;

&lt;p&gt;You don't need to become a data scientist to benefit from link management. But you do need:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Visibility into where your traffic comes from&lt;/strong&gt; (so you know what marketing actually works)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility to update links&lt;/strong&gt; (so a typo doesn't haunt you for years)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Professional branding&lt;/strong&gt; (so your links look like they come from your company, not a random shortener)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost efficiency&lt;/strong&gt; (so you're not burning runway on tools that barely work)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; nails all four.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Setup Takes 20 Minutes
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Sign up at &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; (free)&lt;/li&gt;
&lt;li&gt;Verify your custom domain (5 minutes of DNS config)&lt;/li&gt;
&lt;li&gt;Generate your API key&lt;/li&gt;
&lt;li&gt;Integrate it into your email system, landing pages, or product&lt;/li&gt;
&lt;li&gt;Start tracking&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That's it. No credit card needed. No paywalls.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;Link management isn't glamorous, but it's one of those foundational tools that makes everything else work better. Every founder should have visibility into where their traffic comes from and whether it's actually converting.&lt;/p&gt;

&lt;p&gt;For years, I thought expensive tools were the only way. Then I realized Bitly was charging me $35/month for what Dub gives free. Now I use &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; for everything—email campaigns, social media, product referrals, everything.&lt;/p&gt;

&lt;p&gt;If you're still using basic links or paying Bitly, try &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; for free today. You'll get custom domains, unlimited API calls, team members, and real analytics—all without spending a penny. Your conversion funnel (and your budget) will thank you.&lt;/p&gt;

</description>
      <category>saas</category>
      <category>webdev</category>
      <category>startup</category>
      <category>api</category>
    </item>
    <item>
      <title>Custom Domain URL Shortener: 5 Free Options Compared</title>
      <dc:creator>Joshua</dc:creator>
      <pubDate>Sun, 22 Mar 2026 14:34:16 +0000</pubDate>
      <link>https://forem.com/dubco_tips/custom-domain-url-shortener-5-free-options-compared-2p5m</link>
      <guid>https://forem.com/dubco_tips/custom-domain-url-shortener-5-free-options-compared-2p5m</guid>
      <description>&lt;h1&gt;
  
  
  Custom Domain URL Shortener: 5 Free Options Compared
&lt;/h1&gt;

&lt;p&gt;I've been there. You're sharing a link with a potential client, and it's this ugly &lt;code&gt;yourdomain.com/campaign-landing-page-v3-final-updated-2024&lt;/code&gt; nightmare. They're suspicious of the long URL, you can't track clicks, and it looks unprofessional. That's when I realized: a custom domain shortener isn't just nice-to-have—it's essential for credibility.&lt;/p&gt;

&lt;p&gt;The problem? Most shortener solutions cost $35-100/month just to put your brand on a link. And they charge you extra for the features you actually need: analytics, API access, QR codes.&lt;/p&gt;

&lt;p&gt;I tested 5 free options that let you use your own domain. Here's what I found.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Custom Domain Shorteners Matter
&lt;/h2&gt;

&lt;p&gt;Before we dive into the options, let me explain why this actually matters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Branding&lt;/strong&gt;: &lt;code&gt;mycompany.co/deal&lt;/code&gt; looks infinitely more professional than &lt;code&gt;bit.ly/xyz123&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trust&lt;/strong&gt;: Users click branded links at higher rates because they recognize your domain&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Analytics&lt;/strong&gt;: You need to know &lt;em&gt;how many&lt;/em&gt; people clicked, &lt;em&gt;when&lt;/em&gt;, and &lt;em&gt;from where&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Control&lt;/strong&gt;: Your links don't die if the service shuts down or changes pricing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The wild part? Most free URL shorteners give you zero analytics. They're basically fire-and-forget. You need something that actually gives you data.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 5 Options
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. &lt;strong&gt;Dub.co&lt;/strong&gt; (The Best Option)
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; is what I switched to after years of Bitly frustration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you get free:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unlimited custom domains (yes, really)&lt;/li&gt;
&lt;li&gt;Click analytics with location, device, and referrer data&lt;/li&gt;
&lt;li&gt;Full REST API access (not a pro-plan feature)&lt;/li&gt;
&lt;li&gt;QR codes with custom branding&lt;/li&gt;
&lt;li&gt;Team collaboration&lt;/li&gt;
&lt;li&gt;Webhook support for real-time events&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; Free tier is genuinely unlimited. Pro starts at $20/month (optional).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why it wins:&lt;/strong&gt; Dub.co gives you at the $0 price point what Bitly charges $35/month for. The API access is a game-changer—you can programmatically create links, fetch analytics, or integrate shortening into your app.&lt;/p&gt;

&lt;p&gt;Here's a quick API example:&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;// Create a shortened link with Dub.co&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.dub.co/links&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;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;Content-Type&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;application/json&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;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/long-landing-page&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;mycompany.co&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;summer-sale&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// custom slug&lt;/span&gt;
    &lt;span class="na"&gt;expiresAt&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;Date&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="mi"&gt;30&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// 30 days&lt;/span&gt;
  &lt;span class="p"&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Short link: https://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is production-grade stuff. The webhook system means you can track conversions in real-time.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. &lt;strong&gt;Short.io&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Similar to Dub, but older. Free tier includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 custom domain&lt;/li&gt;
&lt;li&gt;Basic analytics&lt;/li&gt;
&lt;li&gt;Limited API&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; Free for 1 domain, then ~$19/month for more&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The catch:&lt;/strong&gt; API is limited on free tier. You'll hit walls quickly if you're building anything serious.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. &lt;strong&gt;Rebrandly&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Used to be the gold standard. Free tier:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 custom domain&lt;/li&gt;
&lt;li&gt;Basic analytics&lt;/li&gt;
&lt;li&gt;Mobile app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; Free, but pro is $24/month&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem:&lt;/strong&gt; Free tier is ancient. No API access, limited features, clunky UI. It's been overshadowed by newer tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. &lt;strong&gt;TinyURL (with custom domain)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;The classic. Free tier:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic shortening&lt;/li&gt;
&lt;li&gt;Custom domain support&lt;/li&gt;
&lt;li&gt;Simple analytics&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; Free, premium is $5/month&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reality check:&lt;/strong&gt; It works, but it's bare-bones. No API, no advanced features. Fine if you just need to shorten URLs, but not if you're trying to do anything strategic with your data.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. &lt;strong&gt;Bit.ly (Free Tier)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Everyone knows Bit.ly. Free tier:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic link shortening&lt;/li&gt;
&lt;li&gt;Click analytics (limited)&lt;/li&gt;
&lt;li&gt;1 custom domain option&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cost:&lt;/strong&gt; Free, but meaningful features start at $35/month&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why you should avoid it:&lt;/strong&gt; Bit.ly's free tier is a poverty trap. The moment you need decent analytics or API access, they push you to the $35/month plan. That's where I realized &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co's free tier&lt;/a&gt; actually gives you more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature Comparison
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Dub.co&lt;/th&gt;
&lt;th&gt;Short.io&lt;/th&gt;
&lt;th&gt;Rebrandly&lt;/th&gt;
&lt;th&gt;TinyURL&lt;/th&gt;
&lt;th&gt;Bitly&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Free Tier&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom Domains&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Analytics&lt;/td&gt;
&lt;td&gt;Full&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API Access&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QR Codes&lt;/td&gt;
&lt;td&gt;Custom branding&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Webhooks&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No (paid)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Free Forever&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The gap is real. Dub's free tier honestly rivals competitors' $20-35/month plans.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World API Example
&lt;/h2&gt;

&lt;p&gt;Let me show you why API access matters. Say you're running a marketing campaign and need to track which channel drives conversions:&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;// Fetch analytics for a link&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;analytics&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.dub.co/links/mycompany.co/summer-sale/analytics&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;headers&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;analytics&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Total clicks: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clicks&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Top referrer: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;top_referrer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Conversion rate: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;conversion_rate&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;%`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Bit.ly's free tier, you can't do this. You're stuck refreshing a web dashboard. With &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt;, you can automate your entire analytics pipeline.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Cost Comparison
&lt;/h2&gt;

&lt;p&gt;Let's be specific. If you actually need proper link management:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bit.ly Pro&lt;/strong&gt;: $35/month = $420/year&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rebrandly Pro&lt;/strong&gt;: $24/month = $288/year&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Short.io Pro&lt;/strong&gt;: $19/month = $228/year&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dub.co&lt;/strong&gt;: Free forever with better features than their paid competitors&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I switched to Dub because the economics are absurd once you do the math. Why pay $35/month for something you get free with more capabilities?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Catch (Yes, There Is One)
&lt;/h2&gt;

&lt;p&gt;Dub's free tier is genuinely free, but here's what you should know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They make money on higher tiers with advanced features (team management, custom integrations)&lt;/li&gt;
&lt;li&gt;Open-source community keeps the core tool honest&lt;/li&gt;
&lt;li&gt;You're not the product—you're a potential customer they want to impress&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compare that to Bit.ly, which limits your free tier specifically to upsell you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Make the Switch
&lt;/h2&gt;

&lt;p&gt;If you're still using Bit.ly's free tier or debating between options, try &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co free&lt;/a&gt;. No credit card, no limitations on custom domains, full analytics, full API.&lt;/p&gt;

&lt;p&gt;The three things that won me over:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Unlimited custom domains&lt;/strong&gt; on the free plan (game-changer for multi-brand setups)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real API access&lt;/strong&gt; means you can build with it, not just use it&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;QR code branding&lt;/strong&gt; so your QR codes match your brand aesthetic&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I've been using it for 8 months across 12 projects, and I haven't hit a single limitation on the free tier. Start free, upgrade if you hit team collaboration needs. That's the model that actually makes sense.&lt;/p&gt;

&lt;p&gt;Go create your first short link on &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt;—you'll see what I mean immediately.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>marketing</category>
      <category>productivity</category>
      <category>tools</category>
    </item>
    <item>
      <title>I replaced Bitly with an open-source alternative - here is why</title>
      <dc:creator>Joshua</dc:creator>
      <pubDate>Sat, 21 Mar 2026 23:19:26 +0000</pubDate>
      <link>https://forem.com/dubco_tips/i-replaced-bitly-with-an-open-source-alternative-here-is-why-4iga</link>
      <guid>https://forem.com/dubco_tips/i-replaced-bitly-with-an-open-source-alternative-here-is-why-4iga</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Bitly charges $35/month for features that should be free. Custom domains, analytics, QR codes — all locked behind a paywall.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Solution: Dub.co
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://dub.co" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; is an open-source link management platform that gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;25 free links&lt;/strong&gt; with full analytics&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom domains&lt;/strong&gt; on the free tier&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;QR code generation&lt;/strong&gt; built in&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-hosting option&lt;/strong&gt; for unlimited everything&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why I Switched
&lt;/h2&gt;

&lt;p&gt;I was paying Bitly $35/month for my SaaS marketing links. After switching to Dub.co:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Better analytics&lt;/strong&gt; — Dub shows me geographic data, device breakdowns, and referrer sources for free&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom domain&lt;/strong&gt; — I use my own domain for branded links, included in the free tier&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open source&lt;/strong&gt; — I can inspect the code, contribute, and self-host if I outgrow the free tier&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Numbers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Bitly Free&lt;/th&gt;
&lt;th&gt;Bitly Paid ($35/mo)&lt;/th&gt;
&lt;th&gt;Dub.co Free&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Links&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Analytics&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Advanced&lt;/td&gt;
&lt;td&gt;Advanced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom Domain&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QR Codes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Open Source&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Bottom Line
&lt;/h2&gt;

&lt;p&gt;If you are bootstrapping a SaaS or side project, there is no reason to pay for Bitly. Dub.co gives you more features on their free tier than Bitly does on their $35/month plan.&lt;/p&gt;

&lt;p&gt;What link management tool do you use? I would love to hear about alternatives I might have missed.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>saas</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why I Stopped Using Bitly (And What I Switched To)</title>
      <dc:creator>Joshua</dc:creator>
      <pubDate>Sat, 21 Mar 2026 16:10:59 +0000</pubDate>
      <link>https://forem.com/dubco_tips/why-i-stopped-using-bitly-and-what-i-switched-to-cm8</link>
      <guid>https://forem.com/dubco_tips/why-i-stopped-using-bitly-and-what-i-switched-to-cm8</guid>
      <description>&lt;p&gt;A few months ago I hit the wall with Bitly. My free plan ran out of analytics. My branded links looked cheap. And paying $35/month for what should be basic features felt wrong.&lt;/p&gt;

&lt;p&gt;So I went looking for something better. Here is what I found.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bitly Problem
&lt;/h2&gt;

&lt;p&gt;Bitly is great until you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Analytics beyond 30 days&lt;/strong&gt; (locked behind Pro)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom domains&lt;/strong&gt; without paying $35/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API access&lt;/strong&gt; that does not throttle you at 100 requests/month&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Link-in-bio pages&lt;/strong&gt; (not available at all)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For a SaaS builder managing multiple products, these are not nice-to-haves. They are essentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Switched To
&lt;/h2&gt;

&lt;p&gt;I moved everything to &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; and honestly the difference is night and day.&lt;/p&gt;

&lt;p&gt;Here is what the free tier includes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Bitly Free&lt;/th&gt;
&lt;th&gt;Dub.co Free&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Links&lt;/td&gt;
&lt;td&gt;10/month&lt;/td&gt;
&lt;td&gt;25/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Analytics&lt;/td&gt;
&lt;td&gt;30 days&lt;/td&gt;
&lt;td&gt;Forever&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Custom domains&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API calls&lt;/td&gt;
&lt;td&gt;100/month&lt;/td&gt;
&lt;td&gt;1000/month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QR codes&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Advanced&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Link-in-bio&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  My Setup
&lt;/h2&gt;

&lt;p&gt;I use Dub.co for:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Newsletter tracking&lt;/strong&gt; — every link in my emails goes through Dub so I know what readers actually click&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Social media&lt;/strong&gt; — branded short links for Twitter, LinkedIn, Reddit&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API integration&lt;/strong&gt; — I built a simple webhook that creates a short link whenever I publish a new blog post&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The API is dead simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.dub.co/links &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer YOUR_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{ "url": "https://example.com/long-url", "domain": "yourdomain.com" }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Migration
&lt;/h2&gt;

&lt;p&gt;Migrating from Bitly took about 20 minutes:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Export your Bitly links (Settings → Export)&lt;/li&gt;
&lt;li&gt;Import into Dub.co (they have a CSV import)&lt;/li&gt;
&lt;li&gt;Set up your custom domain (just a CNAME record)&lt;/li&gt;
&lt;li&gt;Update your API calls (the Dub API is similar to Bitly but better documented)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Results After 3 Months
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Saved $420/year&lt;/strong&gt; on Bitly Pro&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better analytics&lt;/strong&gt; — I can see click data from 6 months ago&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Faster API&lt;/strong&gt; — No more rate limit errors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Branded links&lt;/strong&gt; — my-domain.co/whatever instead of bit.ly/random&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are still on Bitly, take 20 minutes and try &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt;. The free tier alone beats Bitly Pro.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What link shortener do you use? Drop a comment below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>saas</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How I Manage Links Across 5 SaaS Products Without Paying for Bitly</title>
      <dc:creator>Joshua</dc:creator>
      <pubDate>Sat, 21 Mar 2026 15:49:36 +0000</pubDate>
      <link>https://forem.com/dubco_tips/how-i-manage-links-across-5-saas-products-without-paying-for-bitly-3g8h</link>
      <guid>https://forem.com/dubco_tips/how-i-manage-links-across-5-saas-products-without-paying-for-bitly-3g8h</guid>
      <description>&lt;p&gt;Link management sounds simple until you're running multiple products and each one has different tracking needs, different domains, and different audiences.&lt;/p&gt;

&lt;p&gt;I tried Bitly for a while. It works, but the pricing doesn't make sense for indie developers and small teams. Their custom domain feature alone costs $35/month. Multiply that by 5 products and you're looking at $175/month just for link shortening.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Here's what I needed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Custom domains&lt;/strong&gt; for each product (go.product1.com, links.product2.com, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click analytics&lt;/strong&gt; with geographic data and referrer tracking&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API access&lt;/strong&gt; to automate link creation from my CI/CD pipeline&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free or cheap&lt;/strong&gt; — I'm bootstrapped&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What I Tried
&lt;/h2&gt;

&lt;h3&gt;
  
  
  TinyURL
&lt;/h3&gt;

&lt;p&gt;Free, no analytics. Dead end for anything serious.&lt;/p&gt;

&lt;h3&gt;
  
  
  Short.io
&lt;/h3&gt;

&lt;p&gt;Good analytics but +/month for multiple domains. Same pricing problem as Bitly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rebrandly
&lt;/h3&gt;

&lt;p&gt;Nice UI, but again — custom domains cost money. \/month for branded links.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dub.co
&lt;/h3&gt;

&lt;p&gt;This is what I actually use now. It's &lt;a href="https://github.com/dubinc/dub" rel="noopener noreferrer"&gt;open source&lt;/a&gt;, which immediately caught my attention. Here's what sold me:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Free custom domains&lt;/strong&gt; — unlimited, even on the free tier&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real analytics&lt;/strong&gt; — clicks, geo, referrers, devices. All without paying&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;REST API&lt;/strong&gt; — well-documented, easy to integrate into my deployment scripts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Self-hostable&lt;/strong&gt; — since it's open source, I could host it myself if I wanted (I don't, their hosted version is fast enough)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  My Setup
&lt;/h2&gt;

&lt;p&gt;I have 5 custom domains, each one pointing to a different product. When someone clicks a link, I can see exactly where they came from, what device they're on, and which campaign drove the click.&lt;/p&gt;

&lt;p&gt;My deployment script automatically creates short links for each release. The API call is simple:&lt;/p&gt;

&lt;p&gt;{"error":{"code":"not_found","message":"Workspace ID not found. Did you forget to include a &lt;code&gt;workspaceId&lt;/code&gt; query parameter? It looks like you might be using personal API keys, we also recommend refactoring to workspace API keys: &lt;a href="https://d.to/keys%22,%22doc_url%22:%22https://dub.co/docs/api-reference/errors#not-found%22%7D" rel="noopener noreferrer"&gt;https://d.to/keys","doc_url":"https://dub.co/docs/api-reference/errors#not-found"}&lt;/a&gt;}&amp;lt;!DOCTYPE html&amp;gt;&lt;br&gt;
&lt;br&gt;
    &lt;/p&gt;
&lt;br&gt;
        &lt;br&gt;
        
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;title&amp;gt;Not Found&amp;lt;/title&amp;gt;

    &amp;lt;style&amp;gt;
        /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}a{background-color:transparent}code{font-family:monospace,monospace;font-size:1em}[hidden]{display:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #e2e8f0}a{color:inherit;text-decoration:inherit}code{font-family:Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}svg,video{display:block;vertical-align:middle}video{max-width:100%;height:auto}.bg-white{--bg-opacity:1;background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity))}.bg-gray-100{--bg-opacity:1;background-color:#f7fafc;background-color:rgba(247,250,252,var(--bg-opacity))}.border-gray-200{--border-opacity:1;border-color:#edf2f7;border-color:rgba(237,242,247,var(--border-opacity))}.border-gray-400{--border-opacity:1;border-color:#cbd5e0;border-color:rgba(203,213,224,var(--border-opacity))}.border-t{border-top-width:1px}.border-r{border-right-width:1px}.flex{display:flex}.grid{display:grid}.hidden{display:none}.items-center{align-items:center}.justify-center{justify-content:center}.font-semibold{font-weight:600}.h-5{height:1.25rem}.h-8{height:2rem}.h-16{height:4rem}.text-sm{font-size:.875rem}.text-lg{font-size:1.125rem}.leading-7{line-height:1.75rem}.mx-auto{margin-left:auto;margin-right:auto}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.ml-2{margin-left:.5rem}.mt-4{margin-top:1rem}.ml-4{margin-left:1rem}.mt-8{margin-top:2rem}.ml-12{margin-left:3rem}.-mt-px{margin-top:-1px}.max-w-xl{max-width:36rem}.max-w-6xl{max-width:72rem}.min-h-screen{min-height:100vh}.overflow-hidden{overflow:hidden}.p-6{padding:1.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-8{padding-top:2rem}.fixed{position:fixed}.relative{position:relative}.top-0{top:0}.right-0{right:0}.shadow{box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.text-center{text-align:center}.text-gray-200{--text-opacity:1;color:#edf2f7;color:rgba(237,242,247,var(--text-opacity))}.text-gray-300{--text-opacity:1;color:#e2e8f0;color:rgba(226,232,240,var(--text-opacity))}.text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.text-gray-500{--text-opacity:1;color:#a0aec0;color:rgba(160,174,192,var(--text-opacity))}.text-gray-600{--text-opacity:1;color:#718096;color:rgba(113,128,150,var(--text-opacity))}.text-gray-700{--text-opacity:1;color:#4a5568;color:rgba(74,85,104,var(--text-opacity))}.text-gray-900{--text-opacity:1;color:#1a202c;color:rgba(26,32,44,var(--text-opacity))}.uppercase{text-transform:uppercase}.underline{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.tracking-wider{letter-spacing:.05em}.w-5{width:1.25rem}.w-8{width:2rem}.w-auto{width:auto}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}@-webkit-keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@keyframes spin{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}@-webkit-keyframes ping{0%{transform:scale(1);opacity:1}75%,to{transform:scale(2);opacity:0}}@keyframes ping{0%{transform:scale(1);opacity:1}75%,to{transform:scale(2);opacity:0}}@-webkit-keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}@keyframes pulse{0%,to{opacity:1}50%{opacity:.5}}@-webkit-keyframes bounce{0%,to{transform:translateY(-25%);-webkit-animation-timing-function:cubic-bezier(.8,0,1,1);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:translateY(0);-webkit-animation-timing-function:cubic-bezier(0,0,.2,1);animation-timing-function:cubic-bezier(0,0,.2,1)}}@keyframes bounce{0%,to{transform:translateY(-25%);-webkit-animation-timing-function:cubic-bezier(.8,0,1,1);animation-timing-function:cubic-bezier(.8,0,1,1)}50%{transform:translateY(0);-webkit-animation-timing-function:cubic-bezier(0,0,.2,1);animation-timing-function:cubic-bezier(0,0,.2,1)}}@media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}.sm\:block{display:block}.sm\:items-center{align-items:center}.sm\:justify-start{justify-content:flex-start}.sm\:justify-between{justify-content:space-between}.sm\:h-20{height:5rem}.sm\:ml-0{margin-left:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pt-0{padding-top:0}.sm\:text-left{text-align:left}.sm\:text-right{text-align:right}}@media (min-width:768px){.md\:border-t-0{border-top-width:0}.md\:border-l{border-left-width:1px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}@media (min-width:1024px){.lg\:px-8{padding-left:2rem;padding-right:2rem}}@media (prefers-color-scheme:dark){.dark\:bg-gray-800{--bg-opacity:1;background-color:#2d3748;background-color:rgba(45,55,72,var(--bg-opacity))}.dark\:bg-gray-900{--bg-opacity:1;background-color:#1a202c;background-color:rgba(26,32,44,var(--bg-opacity))}.dark\:border-gray-700{--border-opacity:1;border-color:#4a5568;border-color:rgba(74,85,104,var(--border-opacity))}.dark\:text-white{--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.dark\:text-gray-300 { --text-opacity: 1; color: #e2e8f0; color: rgba(226,232,240,var(--text-opacity)) }}
    &amp;lt;/style&amp;gt;

    &amp;lt;style&amp;gt;
        body {
            font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
        }
    &amp;lt;/style&amp;gt;
&amp;lt;/head&amp;gt;
&amp;lt;body class="antialiased"&amp;gt;
    &amp;lt;div class="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center sm:pt-0" role="main"&amp;gt;
        &amp;lt;div class="max-w-xl mx-auto sm:px-6 lg:px-8"&amp;gt;
            &amp;lt;div class="flex items-center pt-8 sm:justify-start sm:pt-0"&amp;gt;
                &amp;lt;h1 class="px-4 text-lg dark:text-gray-300 text-gray-700 border-r border-gray-400 tracking-wider"&amp;gt;
                    404                    &amp;lt;/h1&amp;gt;

                &amp;lt;div class="ml-4 text-lg dark:text-gray-300 text-gray-700 uppercase tracking-wider"&amp;gt;
                    Not Found                    &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/body&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;h2&gt;
  
  
  Cost Comparison (Monthly)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Custom Domains&lt;/th&gt;
&lt;th&gt;Analytics&lt;/th&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;Monthly Cost&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Bitly&lt;/td&gt;
&lt;td&gt;\/domain&lt;/td&gt;
&lt;td&gt;Pro only&lt;/td&gt;
&lt;td&gt;Pro only&lt;/td&gt;
&lt;td&gt;+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Short.io&lt;/td&gt;
&lt;td&gt;\/domain&lt;/td&gt;
&lt;td&gt;Included&lt;/td&gt;
&lt;td&gt;Included&lt;/td&gt;
&lt;td&gt;+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rebrandly&lt;/td&gt;
&lt;td&gt;\ base&lt;/td&gt;
&lt;td&gt;Included&lt;/td&gt;
&lt;td&gt;Premium&lt;/td&gt;
&lt;td&gt;+&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dub.co&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;\/bin/zsh&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Bottom Line
&lt;/h2&gt;

&lt;p&gt;If you're bootstrapped or running multiple projects, there's no reason to pay for link shortening in 2026. The open-source options have caught up and in many cases surpassed the paid tools.&lt;/p&gt;

&lt;p&gt;Check out &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; if you're in the same boat. The migration from Bitly takes about 10 minutes.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What tools do you use for link management? Curious what others have found works best.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>saas</category>
      <category>tools</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>How I Track Every Click on My Newsletter Links (Open-Source Setup)</title>
      <dc:creator>Joshua</dc:creator>
      <pubDate>Sat, 21 Mar 2026 14:41:25 +0000</pubDate>
      <link>https://forem.com/dubco_tips/how-i-track-every-click-on-my-newsletter-links-open-source-setup-5h5</link>
      <guid>https://forem.com/dubco_tips/how-i-track-every-click-on-my-newsletter-links-open-source-setup-5h5</guid>
      <description>&lt;p&gt;Every week I send a newsletter to ~2,000 subscribers. For months I had &lt;strong&gt;zero idea&lt;/strong&gt; which links people actually clicked. Open rates? Sure, my ESP gives me that. But &lt;em&gt;click-level&lt;/em&gt; data per link? That was a black box.&lt;/p&gt;

&lt;p&gt;I fixed it with a lightweight, open-source-friendly setup that takes about 15 minutes. Here's exactly how.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem With Newsletter Link Tracking
&lt;/h2&gt;

&lt;p&gt;Most email platforms (Substack, ConvertKit, Beehiiv) give you aggregate click counts. But they won't tell you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which &lt;em&gt;specific&lt;/em&gt; links get the most engagement&lt;/li&gt;
&lt;li&gt;Click velocity (how fast people click after open)&lt;/li&gt;
&lt;li&gt;Geographic breakdown per link&lt;/li&gt;
&lt;li&gt;Device/browser split per link&lt;/li&gt;
&lt;li&gt;Long-tail clicks days after sending&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're promoting products, writing sponsored posts, or just trying to figure out what your audience cares about — you need per-link analytics.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;p&gt;Here's what I use:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A link shortener with analytics&lt;/strong&gt; — I use &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; (free tier is generous, API-first)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A simple Node.js script&lt;/strong&gt; to auto-generate tracked links before each send&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A JSON file&lt;/strong&gt; that logs everything for my own dashboards&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Total cost: $0. Total setup time: ~15 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Generate Tracked Links via API
&lt;/h2&gt;

&lt;p&gt;Instead of manually creating short links, I wrote a script that takes my raw newsletter URLs and returns tracked versions.&lt;/p&gt;

&lt;p&gt;First, grab a free API key from &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt;. They have a free tier that covers most newsletter use cases — custom domains, analytics, and API access included.&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;// track-links.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createTrackedLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.dub.co/links&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;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;Content-Type&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;application/json&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;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;tag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="c1"&gt;// optional: set a custom short slug&lt;/span&gt;
      &lt;span class="c1"&gt;// key: 'my-custom-slug',&lt;/span&gt;
    &lt;span class="p"&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shortLink&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage: convert all links in your newsletter draft&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;trackNewsletterLinks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;links&lt;/span&gt;&lt;span class="p"&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;tracked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;links&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;tracked&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createTrackedLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;newsletter-issue-42&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;tracked&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;tracked&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Example&lt;/span&gt;
&lt;span class="nf"&gt;trackNewsletterLinks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;main-article&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;https://myblog.com/post/scaling-postgres&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;sponsor&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;https://sponsor.example.com/promo&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;twitter-thread&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;https://x.com/me/status/123456&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;tool-recommendation&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;https://some-saas.com&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;Run it before each send:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your_key_here"&lt;/span&gt;
node track-links.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;main-article&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://dub.sh/abc123&lt;/span&gt;
&lt;span class="na"&gt;sponsor&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://dub.sh/def456&lt;/span&gt;
&lt;span class="na"&gt;twitter-thread&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://dub.sh/ghi789&lt;/span&gt;
&lt;span class="na"&gt;tool-recommendation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://dub.sh/jkl012&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace the raw URLs in your newsletter with these. Done.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Pull Analytics After Sending
&lt;/h2&gt;

&lt;p&gt;Here's where it gets useful. After your newsletter goes out, pull the click data:&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;// pull-stats.js&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getLinkStats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkId&lt;/span&gt;&lt;span class="p"&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`https://api.dub.co/analytics?linkId=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;linkId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;event=clicks&amp;amp;interval=7d`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getClicksByCountry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkId&lt;/span&gt;&lt;span class="p"&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;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`https://api.dub.co/analytics?linkId=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;linkId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;event=clicks&amp;amp;groupBy=countries`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;headers&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;I run this 24 hours after each send and log the results:&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;fs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;logStats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;issueNumber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;links&lt;/span&gt;&lt;span class="p"&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;stats&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;linkId&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;links&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;clicks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getLinkStats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;countries&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getClicksByCountry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;linkId&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;pulledAt&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;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&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;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`stats/issue-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;issueNumber&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.json`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFileSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stats&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Stats saved to &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;h2&gt;
  
  
  Step 3: Spot Patterns Over Time
&lt;/h2&gt;

&lt;p&gt;After a few issues, the data tells a clear story. Here's what I learned from mine:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Link Type&lt;/th&gt;
&lt;th&gt;Avg CTR&lt;/th&gt;
&lt;th&gt;Insight&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Tutorial links&lt;/td&gt;
&lt;td&gt;12.3%&lt;/td&gt;
&lt;td&gt;Audience wants hands-on content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tool recommendations&lt;/td&gt;
&lt;td&gt;8.7%&lt;/td&gt;
&lt;td&gt;Good, especially with context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Twitter threads&lt;/td&gt;
&lt;td&gt;2.1%&lt;/td&gt;
&lt;td&gt;People don't leave email for X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sponsor links&lt;/td&gt;
&lt;td&gt;5.4%&lt;/td&gt;
&lt;td&gt;Better when placed mid-content&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This completely changed how I structure my newsletter. I moved sponsor links from the footer to the middle of the content and saw a &lt;strong&gt;2.5x increase&lt;/strong&gt; in sponsor clicks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Dub.co Over Other Options
&lt;/h2&gt;

&lt;p&gt;I tried Bitly, TinyURL, and a self-hosted YOURLS instance before settling on &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt;. Here's why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free custom domain&lt;/strong&gt; — your links look professional, not like generic short links&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API-first&lt;/strong&gt; — everything I showed above works because the API is clean and well-documented&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Real analytics&lt;/strong&gt; — geographic, device, referrer, time-series data out of the box&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open source&lt;/strong&gt; — the core is on GitHub, so you can self-host if you want full control&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tags&lt;/strong&gt; — I tag every link with the issue number, so I can filter analytics per newsletter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bitly charges $35/mo for features Dub.co gives you free. YOURLS works but requires server maintenance. Dub.co hit the sweet spot.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus: Automate With a Cron Job
&lt;/h2&gt;

&lt;p&gt;I have a cron job that pulls stats for every issue automatically:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# crontab -e&lt;/span&gt;
0 9 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; MON node /path/to/pull-stats.js &lt;span class="nt"&gt;--issue&lt;/span&gt; latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every Monday morning I have fresh click data waiting in my &lt;code&gt;stats/&lt;/code&gt; folder. I glance at it with my coffee and know exactly what resonated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;If you're sending a newsletter without per-link tracking, you're flying blind. This setup is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Free&lt;/strong&gt; (Dub.co free tier + Node.js)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast&lt;/strong&gt; (15 min setup, &amp;lt;1 min per issue after that)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Private&lt;/strong&gt; (your data, your JSON files, no third-party dashboard lock-in)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Grab a free Dub.co API key at &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;dub.co&lt;/a&gt; and start tracking. Your newsletter strategy will thank you.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have questions about the setup? Drop a comment — happy to share my full config.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>newsletter</category>
      <category>analytics</category>
      <category>webdev</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Why I Switched from Bitly to Dub.co (And Saved $420/Year)</title>
      <dc:creator>Joshua</dc:creator>
      <pubDate>Sat, 21 Mar 2026 14:33:04 +0000</pubDate>
      <link>https://forem.com/dubco_tips/why-i-switched-from-bitly-to-dubco-and-saved-420year-1on0</link>
      <guid>https://forem.com/dubco_tips/why-i-switched-from-bitly-to-dubco-and-saved-420year-1on0</guid>
      <description>&lt;h1&gt;
  
  
  Why I Switched from Bitly to Dub.co (And Saved $420/Year)
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The $35/Month Link Problem
&lt;/h2&gt;

&lt;p&gt;I was paying Bitly $420 a year. Not for some enterprise behemoth solution, but for the ability to track link clicks and use a custom domain.&lt;/p&gt;

&lt;p&gt;That realization hit me during a budget review last quarter. Here I was, a developer who builds my own analytics dashboards and APIs, paying premium prices for basic link management. The irony wasn't lost on me.&lt;/p&gt;

&lt;p&gt;Then I found &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It's not just a cheaper alternative—it's what Bitly was supposed to evolve into before they pivoted to enterprise. In the three months since switching, I've not only killed that $420/year subscription, I've gotten &lt;em&gt;better&lt;/em&gt; tools in the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Was Stuck on Bitly
&lt;/h2&gt;

&lt;p&gt;Bitly's free plan is genuinely limiting. No custom domains. No API access. No team features. If you want any of the features developers actually need, you're forking over $35/month for the Pro plan.&lt;/p&gt;

&lt;p&gt;Over two years, that's $840. For link shortening. In 2024.&lt;/p&gt;

&lt;p&gt;The Pro plan gave me:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One custom domain&lt;/li&gt;
&lt;li&gt;Basic click tracking&lt;/li&gt;
&lt;li&gt;API access&lt;/li&gt;
&lt;li&gt;Custom QR codes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Standard stuff. Things that shouldn't require a subscription tier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Discovery
&lt;/h2&gt;

&lt;p&gt;I was building a launch page for a side project and needed programmatic link creation with custom domains. Another $35/month felt wasteful, so I started comparing alternatives.&lt;/p&gt;

&lt;p&gt;That's when Dub.co appeared in my search results. The landing page was immediately different from typical SaaS marketing—it listed what you get &lt;em&gt;for free&lt;/em&gt;, not what you unlock at each pricing tier. And the free tier was... everything I was paying for.&lt;/p&gt;

&lt;p&gt;Custom domain? Free. API access? Free. Analytics? Free. QR codes? Free.&lt;/p&gt;

&lt;p&gt;I was skeptical. Something was wrong. Let me dig in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Feature Comparison: Bitly Pro vs Dub.co Free
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Bitly Pro ($35/mo)&lt;/th&gt;
&lt;th&gt;Dub.co Free&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Custom domains&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API access&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes, full REST API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Click analytics&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Advanced (real-time, geographic, device, referrer)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QR codes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes, with branding&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team members&lt;/td&gt;
&lt;td&gt;Up to 3&lt;/td&gt;
&lt;td&gt;Unlimited on free&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Webhook support&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Link previews&lt;/td&gt;
&lt;td&gt;Basic&lt;/td&gt;
&lt;td&gt;Advanced with OG customization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cost per year&lt;/td&gt;
&lt;td&gt;$420&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That's not a typo. Dub's free tier legitimately outmaneuvers Bitly's paid tier on most metrics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Test: Building a Link Tracking System
&lt;/h2&gt;

&lt;p&gt;Before fully switching, I needed to verify the API actually worked for production use.&lt;/p&gt;

&lt;p&gt;Here's what I built in 15 minutes with Dub's API (compared to what would take 30+ minutes with Bitly's):&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;fetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createTrackedLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;domain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;your-domain.com&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.dub.co/links&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;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;Content-Type&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;application/json&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;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`campaign-&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// Custom key&lt;/span&gt;
      &lt;span class="na"&gt;expiresAt&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;Date&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="mi"&gt;30&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;60&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// 30 days&lt;/span&gt;
    &lt;span class="p"&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;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shortUrl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="nf"&gt;createTrackedLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/long-url&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="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shortUrl&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Tracked: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;shortUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. The API is RESTful, well-documented, and doesn't require jumping through OAuth hoops.&lt;/p&gt;

&lt;p&gt;Compare that to Bitly's approach, which requires setting up an OAuth app just to test locally. Dub treats API access like it should be: a standard feature, not a gated extra.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Migration (Surprisingly Easy)
&lt;/h2&gt;

&lt;p&gt;I expected migrating 200+ active links to be painful. It wasn't.&lt;/p&gt;

&lt;p&gt;Dub's bulk import handled CSV files directly. I exported my Bitly links, cleaned up formatting in under 5 minutes, and uploaded. Within seconds, all links were active on my new domain.&lt;/p&gt;

&lt;p&gt;The existing short links? I used Bitly's redirect forwarding to tunnel everything to the Dub equivalents for a week, then updated documentation. Zero broken links. Zero downtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analytics That Actually Matter
&lt;/h2&gt;

&lt;p&gt;Here's where Dub genuinely surprised me.&lt;/p&gt;

&lt;p&gt;Bitly's analytics are... fine. You see click counts and rough geographic data. Dub's free analytics include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-time click tracking&lt;/strong&gt; — I can watch clicks come in as they happen&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Device breakdown&lt;/strong&gt; — Separate metrics for mobile, tablet, desktop&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Referrer tracking&lt;/strong&gt; — Which sites are sending traffic (not just "direct")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;QR code scans vs link clicks&lt;/strong&gt; — Split tracking for different campaign channels&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom metadata&lt;/strong&gt; — Tag links with campaign info, then aggregate in dashboards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This matters. When I launched a product, I could see that one referrer was driving 3x the traffic of another in real time. Optimized accordingly. Would've missed that with Bitly's dashboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Open Source Angle
&lt;/h2&gt;

&lt;p&gt;Dub is &lt;a href="https://github.com/dubinc/dub" rel="noopener noreferrer"&gt;open source&lt;/a&gt;. The entire platform is on GitHub.&lt;/p&gt;

&lt;p&gt;For a link shortener, this means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can see exactly how your data is handled&lt;/li&gt;
&lt;li&gt;No vendor lock-in at the architectural level&lt;/li&gt;
&lt;li&gt;The community contributes features (and catches security issues)&lt;/li&gt;
&lt;li&gt;You could self-host if needed (though I use their cloud)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's the kind of transparency I expect from tools in 2024. Bitly's source is closed. You trust them or you don't.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Numbers
&lt;/h2&gt;

&lt;p&gt;Annual savings: &lt;strong&gt;$420&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Time saved on setup and migration: &lt;strong&gt;About 3 hours&lt;/strong&gt;, which would've cost more than the annual savings if I valued my time normally. (I don't. I enjoy this stuff.)&lt;/p&gt;

&lt;p&gt;Features gained over Bitly Pro:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unlimited custom domains (instead of 1)&lt;/li&gt;
&lt;li&gt;Webhook support for automation&lt;/li&gt;
&lt;li&gt;Better analytics&lt;/li&gt;
&lt;li&gt;Open-source infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Features lost: None that I actually used.&lt;/p&gt;

&lt;h2&gt;
  
  
  One Catch (There's Always One)
&lt;/h2&gt;

&lt;p&gt;Dub's paid plans ($10/month and up) are for teams and power users. If you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;More than basic branding customization&lt;/li&gt;
&lt;li&gt;Dedicated support&lt;/li&gt;
&lt;li&gt;White-label options&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...then you'll want to upgrade. That's fair. But for 95% of developers and small SaaS founders, the free tier is complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should You Switch?
&lt;/h2&gt;

&lt;p&gt;If you're paying for Bitly (or any other expensive link shortener), the answer is yes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Sign up for free at Dub.co&lt;/a&gt;. Create a custom domain. Build a link via API. Run an analytics query. You'll see in 20 minutes what took me a week to figure out.&lt;/p&gt;

&lt;p&gt;The best part: if it doesn't work for you, you've lost nothing. No credit card. No trial period. No dark pattern upsells. Just a link shortener that respects your time and your budget.&lt;/p&gt;

&lt;p&gt;Three months in, the only regret I have is not making the switch earlier.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ready to kill your Bitly subscription?&lt;/strong&gt; &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Start free with Dub.co&lt;/a&gt;—custom domains, API, and real analytics included.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>tools</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Automate Your Marketing Links with Dub.co and Node.js</title>
      <dc:creator>Joshua</dc:creator>
      <pubDate>Sat, 21 Mar 2026 14:01:15 +0000</pubDate>
      <link>https://forem.com/dubco_tips/automate-your-marketing-links-with-dubco-and-nodejs-402</link>
      <guid>https://forem.com/dubco_tips/automate-your-marketing-links-with-dubco-and-nodejs-402</guid>
      <description>&lt;h1&gt;
  
  
  Automate Your Marketing Links with Dub.co and Node.js
&lt;/h1&gt;

&lt;p&gt;If you're running campaigns across email, social, and paid ads, you know the pain: dozens of links to create, tag, and track. Most teams do this manually in Bitly's dashboard, one link at a time. That's slow, error-prone, and doesn't scale.&lt;/p&gt;

&lt;p&gt;I built a Node.js script that automates the entire workflow using the &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; API. It creates branded short links in bulk, applies UTM parameters automatically, and pipes click data into a dashboard. The whole thing took an afternoon.&lt;/p&gt;

&lt;p&gt;Here's how to build it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Automate Link Management?
&lt;/h2&gt;

&lt;p&gt;Manual link creation breaks down fast:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Campaign launches&lt;/strong&gt; need 10-20 links (one per channel, variant, audience segment)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;UTM parameters&lt;/strong&gt; get inconsistent when humans type them&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tracking&lt;/strong&gt; requires checking each link individually&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reporting&lt;/strong&gt; means exporting CSVs from multiple dashboards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Automation fixes all of this. One script, one command, consistent links with analytics built in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Dub.co Over Bitly for Automation
&lt;/h2&gt;

&lt;p&gt;I tried automating with Bitly first. Two problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Rate limits on the free tier are brutal&lt;/strong&gt; — 100 links/month, and the API is throttled&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom domains cost $35/month&lt;/strong&gt; — just to use your own brand in links&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Free custom domains&lt;/li&gt;
&lt;li&gt;1,000 links/month on the free plan&lt;/li&gt;
&lt;li&gt;Clean REST API with no weird auth hoops&lt;/li&gt;
&lt;li&gt;Built-in analytics (geo, device, referrer)&lt;/li&gt;
&lt;li&gt;Free QR code generation per link&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For automation, the generous free tier is what matters most. You can actually build something useful without hitting a paywall.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Set Up Your Dub.co Workspace
&lt;/h2&gt;

&lt;p&gt;Sign up at &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; and grab your API key from the dashboard under &lt;strong&gt;Settings → API Keys&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Optional but recommended: add a custom domain. Go to &lt;strong&gt;Settings → Domains&lt;/strong&gt;, add something like &lt;code&gt;go.yoursite.com&lt;/code&gt;, and point a CNAME record to &lt;code&gt;clink.dub.co&lt;/code&gt;. This takes 2 minutes and makes every link you create on-brand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Install Dependencies
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir &lt;/span&gt;link-automator &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;link-automator
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;node-fetch dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a &lt;code&gt;.env&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DUB_API_KEY=your_api_key_here
DUB_DOMAIN=go.yoursite.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Build the Link Creator
&lt;/h2&gt;

&lt;p&gt;Here's the core script that creates branded links with UTM parameters:&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;// create-links.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;config&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;DUB_API&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.dub.co&lt;/span&gt;&lt;span class="dl"&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;headers&lt;/span&gt; &lt;span class="o"&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;Content-Type&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;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createLink&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;campaign&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;channel&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Append UTM parameters automatically&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;targetUrl&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;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;targetUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&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="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;targetUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&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;link&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;targetUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&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="nx"&gt;campaign&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;DUB_API&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/links`&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;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;targetUrl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_DOMAIN&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dub.sh&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;externalId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;campaign&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;tagIds&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="c1"&gt;// add tag IDs from your workspace&lt;/span&gt;
    &lt;span class="p"&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Define your campaign links&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;campaignLinks&lt;/span&gt; &lt;span class="o"&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;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://yoursite.com/launch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;launch-tw&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;campaign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spring-launch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;twitter&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;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://yoursite.com/launch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;launch-em&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;campaign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spring-launch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;channel&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://yoursite.com/launch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;launch-li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;campaign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spring-launch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;linkedin&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;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://yoursite.com/launch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;launch-rd&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;campaign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spring-launch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;reddit&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;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://yoursite.com/launch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;slug&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;launch-yt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;campaign&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spring-launch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;youtube&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Creating &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;campaignLinks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; links...\n`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;for &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;link&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;campaignLinks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&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;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;createLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`✓ &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: https://&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;result&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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`✗ &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;channel&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node create-links.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;Creating 5 links...

✓ twitter: https://go.yoursite.com/launch-tw
✓ email: https://go.yoursite.com/launch-em
✓ linkedin: https://go.yoursite.com/launch-li
✓ reddit: https://go.yoursite.com/launch-rd
✓ youtube: https://go.yoursite.com/launch-yt
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Five branded, tracked links in under a second. Each one has consistent UTM parameters and an &lt;code&gt;externalId&lt;/code&gt; you can use to query analytics later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Pull Click Analytics
&lt;/h2&gt;

&lt;p&gt;Now the powerful part — pulling click data programmatically:&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;// analytics.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;config&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;headers&lt;/span&gt; &lt;span class="o"&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getCampaignStats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;campaign&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Get all links for this campaign&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;linksRes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`https://api.dub.co/links?search=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;campaign&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&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;links&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;linksRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`\n--- Campaign: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;campaign&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; ---`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Total links: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;links&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;totalClicks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;for &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;link&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;links&lt;/span&gt;&lt;span class="p"&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;clicks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clicks&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;totalClicks&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;clicks&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// Get detailed analytics for high-performing links&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;clicks&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&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;analyticsRes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s2"&gt;`https://api.dub.co/analytics?linkId=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;event=clicks&amp;amp;groupBy=countries`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&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;geo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;analyticsRes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;link&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="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;clicks&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; clicks`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`  Top countries: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;geo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; (&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clicks&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;, &lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;link&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="s2"&gt;: 0 clicks`&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;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`\nTotal campaign clicks: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;totalClicks&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;getCampaignStats&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;spring-launch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives you per-link and per-country breakdowns without ever opening a dashboard.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: Schedule It with Cron
&lt;/h2&gt;

&lt;p&gt;For ongoing campaigns, schedule the analytics script to run daily and send you a summary:&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;// daily-report.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dotenv&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;dailyReport&lt;/span&gt;&lt;span class="p"&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;headers&lt;/span&gt; &lt;span class="o"&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="c1"&gt;// Get analytics for the last 24 hours&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.dub.co/analytics?event=clicks&amp;amp;groupBy=top_links&amp;amp;interval=24h&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="nx"&gt;headers&lt;/span&gt; &lt;span class="p"&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;topLinks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;report&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;topLinks&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clicks&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;link&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="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clicks&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; clicks`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Daily Link Report (&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;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toLocaleDateString&lt;/span&gt;&lt;span class="p"&gt;()}&lt;/span&gt;&lt;span class="s2"&gt;)`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;report&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;No clicks in the last 24 hours&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Pipe this to Slack, email, or wherever you want&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nf"&gt;dailyReport&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add it to your crontab:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run daily at 9 AM&lt;/span&gt;
0 9 &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;cd&lt;/span&gt; /path/to/link-automator &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; node daily-report.js &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /var/log/link-report.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Bigger Picture
&lt;/h2&gt;

&lt;p&gt;Once your links are created programmatically, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A/B test landing pages&lt;/strong&gt; by creating multiple links to different URLs and comparing click-through rates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto-expire links&lt;/strong&gt; for time-limited promos using Dub.co's expiration feature&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generate QR codes&lt;/strong&gt; for each link (Dub.co creates them automatically)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tag links by team member&lt;/strong&gt; so everyone can see which channels perform&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The API supports all of this. Check the &lt;a href="https://dub.co/docs" rel="noopener noreferrer"&gt;Dub.co docs&lt;/a&gt; for the full reference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;Link management shouldn't be manual work. With &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; and a simple Node.js script, you can create, track, and report on hundreds of links without touching a dashboard.&lt;/p&gt;

&lt;p&gt;The free tier gives you everything you need to get started — custom domains, analytics, and a clean API. If you're still creating links one by one in Bitly, give &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; a shot. Your future self will thank you.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Have questions about the setup? Drop a comment and I'll help you out.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>marketing</category>
    </item>
    <item>
      <title>Why I Switched from Bitly to Dub.co (And Saved $420/Year)</title>
      <dc:creator>Joshua</dc:creator>
      <pubDate>Sat, 21 Mar 2026 13:55:18 +0000</pubDate>
      <link>https://forem.com/dubco_tips/why-i-switched-from-bitly-to-dubco-and-saved-420year-3j0n</link>
      <guid>https://forem.com/dubco_tips/why-i-switched-from-bitly-to-dubco-and-saved-420year-3j0n</guid>
      <description>&lt;p&gt;If you're still paying for Bitly in 2026, you might want to read this.&lt;/p&gt;

&lt;p&gt;I've been using link shorteners for years — tracking clicks on newsletter links, social posts, client campaigns. Bitly was always the default. Then they moved everything behind a paywall. Custom domains? $35/month. Decent analytics? Pay up. Even basic branded links now need a subscription.&lt;/p&gt;

&lt;p&gt;I finally looked for alternatives and found &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pricing Problem
&lt;/h2&gt;

&lt;p&gt;Here's what Bitly charges in 2026:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Bitly&lt;/th&gt;
&lt;th&gt;Dub.co&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Custom domain&lt;/td&gt;
&lt;td&gt;$35/mo&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Links per month&lt;/td&gt;
&lt;td&gt;100 (free)&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1,000 (free)&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Click analytics&lt;/td&gt;
&lt;td&gt;Paid only&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API access&lt;/td&gt;
&lt;td&gt;$29/mo+&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QR codes&lt;/td&gt;
&lt;td&gt;Paid&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Free&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team workspaces&lt;/td&gt;
&lt;td&gt;$199/mo&lt;/td&gt;
&lt;td&gt;$24/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That's a &lt;strong&gt;$420/year savings&lt;/strong&gt; just on the basic plan. And Dub.co's free tier is more generous than Bitly's paid starter.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Actually Made Me Switch
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Free Custom Domains
&lt;/h3&gt;

&lt;p&gt;With Bitly, using your own domain (like &lt;code&gt;go.yoursite.com&lt;/code&gt;) costs $35/month. With &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt;, you get custom domains on the free plan. You just add a DNS record and you're done.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Better Developer Experience
&lt;/h3&gt;

&lt;p&gt;The API is clean and well-documented. Here's how simple it is to create a short link:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.dub.co/links &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer YOUR_API_KEY"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"url": "https://example.com", "domain": "yourdomain.com"}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare that to Bitly's API which requires OAuth tokens and has rate limits that'll make you cry on the free tier.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Open Source
&lt;/h3&gt;

&lt;p&gt;This is the big one. &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co is fully open source&lt;/a&gt;. You can inspect the code, self-host it, or contribute. Try doing that with Bitly.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Analytics That Don't Suck
&lt;/h3&gt;

&lt;p&gt;Real-time click tracking, geographic data, device breakdowns, referrer info — all on the free plan. Bitly gates most analytics behind their Pro plan ($35/mo).&lt;/p&gt;

&lt;h2&gt;
  
  
  The Migration
&lt;/h2&gt;

&lt;p&gt;Moving was painless. Dub.co lets you import existing links, and your old Bitly links keep working (they're just short URLs). I migrated about 200 links in under 10 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who Should Switch?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Developers&lt;/strong&gt; who need API access without paying enterprise prices&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Marketers&lt;/strong&gt; who want custom domains and analytics without the Bitly tax&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Startups&lt;/strong&gt; that need a professional link shortener without burning budget&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anyone&lt;/strong&gt; tired of Bitly's constant upsells&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Bottom Line
&lt;/h2&gt;

&lt;p&gt;I was paying Bitly $35/month for features that &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;Dub.co gives away free&lt;/a&gt;. After 6 months of using it, I haven't looked back. The free tier handles everything I need, the API is better, and being open source means I'm not locked into a vendor that keeps raising prices.&lt;/p&gt;

&lt;p&gt;If you're evaluating link shorteners, &lt;a href="https://refer.dub.co/shamil" rel="noopener noreferrer"&gt;give Dub.co a try&lt;/a&gt;. The free plan is legitimately useful — no credit card required, no 14-day trial bait.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What link shortener are you using? Have you tried any Bitly alternatives? Drop your experience in the comments.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>tools</category>
      <category>opensource</category>
    </item>
    <item>
      <title>The Best Bitly Alternative in 2026 (Free Custom Domain Included)</title>
      <dc:creator>Joshua</dc:creator>
      <pubDate>Sat, 21 Mar 2026 13:54:44 +0000</pubDate>
      <link>https://forem.com/dubco_tips/the-best-bitly-alternative-in-2026-free-custom-domain-included-4fke</link>
      <guid>https://forem.com/dubco_tips/the-best-bitly-alternative-in-2026-free-custom-domain-included-4fke</guid>
      <description>&lt;h1&gt;
  
  
  The Best Bitly Alternative in 2026 (Free Custom Domain Included)
&lt;/h1&gt;

&lt;p&gt;You're building something meaningful—a SaaS product, a content empire, a newsletter with real traction. Then you hit that moment: you need to share links professionally, track clicks, and suddenly Bitly's pricing hits you like a truck. $35/month just to get a custom domain? For link shortening?&lt;/p&gt;

&lt;p&gt;If that sounds familiar, I've been there. And I found something better.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bitly Problem (and Why It Still Exists)
&lt;/h2&gt;

&lt;p&gt;Bitly has been the default for a decade. But defaults don't always stay great. Their free plan gives you basic link shortening and zero custom domains. Their pro plan—the one you actually need—costs $35/month. For that price, you get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One custom domain&lt;/li&gt;
&lt;li&gt;Standard analytics&lt;/li&gt;
&lt;li&gt;Limited API access&lt;/li&gt;
&lt;li&gt;No team collaboration on the free tier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Meanwhile, the indie dev and creator landscape has exploded. People need more. And they shouldn't have to pay enterprise prices to get it.&lt;/p&gt;

&lt;p&gt;I switched to &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;&lt;strong&gt;Dub.co&lt;/strong&gt;&lt;/a&gt; three months ago, and honestly, I'm not sure why anyone still uses Bitly for this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter Dub.co: The Modern Link Platform
&lt;/h2&gt;

&lt;p&gt;Dub.co is what Bitly should be in 2026. Here's the part that still surprises me—&lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;everything below is free&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Custom domain&lt;/strong&gt; (your own branded short links)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full analytics&lt;/strong&gt; (clicks, referrers, devices, geography)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;API access&lt;/strong&gt; (programmatic link creation and management)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;QR codes&lt;/strong&gt; (with custom branding)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Team collaboration&lt;/strong&gt; (add team members for free)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;No credit card required. No feature gate hiding behind a paywall. You get the tools that Bitly charges $420/year for, included by default.&lt;/p&gt;

&lt;h2&gt;
  
  
  How They Stack Up: The Numbers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Bitly Free&lt;/th&gt;
&lt;th&gt;Bitly Pro&lt;/th&gt;
&lt;th&gt;Dub.co Free&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Custom Domain&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API Access&lt;/td&gt;
&lt;td&gt;Limited&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;QR Codes&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Advanced Analytics&lt;/td&gt;
&lt;td&gt;❌&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;td&gt;✅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Team Members&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Unlimited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Price/Month&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;$35&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;That's not a small difference. That's a paradigm shift.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Makes Dub.co Actually Better
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. It's Actually Developer-Friendly&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Dub.co treats developers like first-class citizens. The API documentation is clear, the SDKs exist for multiple languages, and there's no artificial gatekeeping. Here's what creating a short link looks like:&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;// Using the Dub.co API&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.dub.co/links&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;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;Content-Type&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;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://yoursite.com/long-article-about-seo&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short.yourcompany.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;shortCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;seo-guide&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tags&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;guide&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;seo&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;marketing&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="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;shortUrl&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Share this: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;shortUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare that to Bitly's API (where half the features require paid plans). Dub.co just... gives you everything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Custom Domains That Actually Work&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You want &lt;code&gt;share.yourcompany.com&lt;/code&gt; instead of &lt;code&gt;bit.ly/xyz123&lt;/code&gt;. With Dub.co, that's step one. The domain setup is straightforward—add a CNAME record, wait for verification, done. Your links instantly look legitimate because they &lt;em&gt;are&lt;/em&gt; legitimate.&lt;/p&gt;

&lt;p&gt;Marketing teams love this. It builds brand trust. Analytics tools don't penalize your links for being from a third-party shortener (some do, especially if they're from generic shorteners).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Analytics That Tell You Something&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bitly's analytics show you clicks. Dub.co's analytics show you &lt;em&gt;why&lt;/em&gt; people clicked.&lt;/p&gt;

&lt;p&gt;You see:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Referrer sources (Twitter, Slack, email, organic?)&lt;/li&gt;
&lt;li&gt;Device type and OS&lt;/li&gt;
&lt;li&gt;Geographic location (country, city, even metro)&lt;/li&gt;
&lt;li&gt;Real-time dashboards&lt;/li&gt;
&lt;li&gt;Detailed CSV exports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For creators and marketers, this is gold. You finally understand which content, which channels, which times drive actual engagement.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. QR Codes With Branding&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This one seems small but changes everything. You can create QR codes with your logo embedded. Not just functional—visually yours. Perfect for printed materials, presentations, even merch.&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;// Generate a branded QR code with Dub.co&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;qrCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.dub.co/qr&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;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://yoursite.com/product&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;logo&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://yoursite.com/logo.png&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;5. Open Source (If You Care About That)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Dub.co is built on open-source principles. The codebase is on GitHub. You can self-host if you want. You're not locked into someone else's infrastructure. That's the opposite of vendor lock-in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Example: Building a Link-Tracking Dashboard
&lt;/h2&gt;

&lt;p&gt;Let's say you run a newsletter and need to track which stories get the most traction. Here's how you'd set that up with Dub.co:&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;// Track newsletter link performance&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createNewsletterLink&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;storyTitle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;storyUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;issue&lt;/span&gt;&lt;span class="p"&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;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.dub.co/links&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;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;Content-Type&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;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;storyUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;newsletter.yoursite.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;shortCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`issue-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;issue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-story-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;storyTitle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toLowerCase&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;`newsletter-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;issue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;story&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="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Later: retrieve analytics&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getNewsletterPerformance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;issue&lt;/span&gt;&lt;span class="p"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;`https://api.dub.co/analytics?domain=newsletter.yoursite.com&amp;amp;tag=newsletter-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;issue&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;headers&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_API_KEY&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Gets clicks, referrers, devices, all organized&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Bitly's free tier, you can't even do this. With their paid tier, you're paying $420/year. With &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt;? It's free, and the API is actually built for this use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Cost Reality Check
&lt;/h2&gt;

&lt;p&gt;Here's what you actually save by switching:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Personal project&lt;/strong&gt;: $0 vs. $35/month = $420/year saved&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Small team (3-5 people)&lt;/strong&gt;: Still $0 vs. $105+/month = $1,260/year saved&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Content creator tracking 20+ properties&lt;/strong&gt;: Still $0 (team features unlimited)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're running this at scale—multiple brands, multiple custom domains, team collaboration—&lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; saves you thousands annually while giving you &lt;em&gt;better&lt;/em&gt; tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters for Your Business
&lt;/h2&gt;

&lt;p&gt;Links are everywhere in modern marketing. They're in newsletters, social media, ads, presentations, emails. If you're treating them as disposable, you're leaving data on the table.&lt;/p&gt;

&lt;p&gt;With proper link management:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You understand which content actually converts&lt;/li&gt;
&lt;li&gt;Your brand stays consistent (custom domains)&lt;/li&gt;
&lt;li&gt;You can iterate faster (real data)&lt;/li&gt;
&lt;li&gt;Your team stays aligned (collaboration features)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Bitly made you pay extra for these basics. Dub.co just... includes them.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;I've been using &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; for three months across three different projects. I've never once wished for Bitly. The feature parity isn't even close—Dub.co wins on price, wins on features, and wins on developer experience.&lt;/p&gt;

&lt;p&gt;If you're still on Bitly because you think that's your only option, try &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co free&lt;/a&gt; today. No credit card. No trial period expiring. Just better tools, from day one.&lt;/p&gt;

&lt;p&gt;Your future analytics dashboard will thank you.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>seo</category>
      <category>marketing</category>
      <category>tools</category>
    </item>
    <item>
      <title>Link Analytics That Actually Make Sense: Dub.co vs. Bitly vs. Short.io</title>
      <dc:creator>Joshua</dc:creator>
      <pubDate>Fri, 13 Mar 2026 04:30:47 +0000</pubDate>
      <link>https://forem.com/dubco_tips/link-analytics-that-actually-make-sense-dubco-vs-bitly-vs-shortio-55ao</link>
      <guid>https://forem.com/dubco_tips/link-analytics-that-actually-make-sense-dubco-vs-bitly-vs-shortio-55ao</guid>
      <description>&lt;h1&gt;
  
  
  Link Analytics That Actually Make Sense: Dub.co vs. Bitly vs. Short.io
&lt;/h1&gt;

&lt;p&gt;You're running a campaign. Traffic's flowing. But when you check your link analytics, you get nothing but a vanity metric and a bill for $35/month.&lt;/p&gt;

&lt;p&gt;This is the Bitly experience in 2024.&lt;/p&gt;

&lt;p&gt;I've been there. You set up a shortened link, share it across channels, and then... you can't tell which traffic source converted, what the click-through rate actually means, or whether your campaign ROI is positive. The platform makes money from your uncertainty. Meanwhile, better tools exist that give you everything—for free.&lt;/p&gt;

&lt;p&gt;After testing Bitly, Short.io, and Dub.co across three campaigns, I switched to Dub.co and haven't looked back. Here's what I learned.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Link Analytics Matter (And Why Bitly Fails)
&lt;/h2&gt;

&lt;p&gt;Shortened links are deceptively important. They're your data collection points. Every click is a potential signal: which channel works, which content resonates, which audience buys.&lt;/p&gt;

&lt;p&gt;But Bitly's free plan gives you almost nothing. No click geography. No UTM parameter visibility. No API access. Want those features? That's $35/month—more if your team is larger.&lt;/p&gt;

&lt;p&gt;For most marketers, that's a non-starter. You don't pay $35/month to understand what you should already know.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Comparison
&lt;/h2&gt;

&lt;p&gt;Here's what I found testing each platform:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;Dub.co&lt;/th&gt;
&lt;th&gt;Bitly&lt;/th&gt;
&lt;th&gt;Short.io&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Free Plan Cost&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;td&gt;$0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom Domain&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓ (included)&lt;/td&gt;
&lt;td&gt;✗ (paid)&lt;/td&gt;
&lt;td&gt;✓ (paid tier)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Full Analytics&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓ (free)&lt;/td&gt;
&lt;td&gt;✗ (limited)&lt;/td&gt;
&lt;td&gt;✓ (limited free)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;API Access&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓ (free)&lt;/td&gt;
&lt;td&gt;✗ (paid)&lt;/td&gt;
&lt;td&gt;✓ (limited)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;QR Codes&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓ (branded)&lt;/td&gt;
&lt;td&gt;✓ (basic)&lt;/td&gt;
&lt;td&gt;✓ (basic)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Webhooks&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Team Collaboration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✓&lt;/td&gt;
&lt;td&gt;✗&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Monthly Cost (Full Features)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Free&lt;/td&gt;
&lt;td&gt;$35+&lt;/td&gt;
&lt;td&gt;$25+&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Dub.co wins on price, but that's not the whole story. Let me show you the practical difference.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Dub.co Actually Works
&lt;/h2&gt;

&lt;p&gt;I set up a campaign with an affiliate link (I'm using &lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; myself for link management). Here's what I got instantly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A custom domain link: &lt;code&gt;mysite.link/campaign-name&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click tracking by geography, device, browser, and referrer&lt;/li&gt;
&lt;li&gt;UTM parameter preservation (I can see exactly what my tracking actually caught)&lt;/li&gt;
&lt;li&gt;A branded QR code to print on materials&lt;/li&gt;
&lt;li&gt;Webhook notifications when someone clicks (I built a Slack integration)&lt;/li&gt;
&lt;li&gt;Full API access to automate everything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The API is the killer feature. With Bitly's paid tier, you get API access. With Dub.co's free tier, you &lt;em&gt;also&lt;/em&gt; get it. Here's an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST https://api.dub.co/links &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer YOUR_TOKEN"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "url": "https://example.com/page?utm_source=twitter",
    "domain": "mysite.link",
    "key": "campaign-123",
    "expiresAt": "2024-12-31"
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. You create shortened links programmatically. You can batch them. You can set expiration dates. You can track which links perform best, in real-time.&lt;/p&gt;

&lt;p&gt;Bitly makes you pay $99/month for that. Short.io charges $25/month and still limits your API calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  Building a Tracking System
&lt;/h2&gt;

&lt;p&gt;Here's a practical example. Say you're running ads on three platforms and want to know which converts best.&lt;/p&gt;

&lt;p&gt;With Dub.co's API, you can create links for each platform in a loop:&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;platforms&lt;/span&gt; &lt;span class="o"&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;twitter&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;linkedin&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;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;for &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;platform&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;platforms&lt;/span&gt;&lt;span class="p"&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;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.dub.co/links&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;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;headers&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DUB_TOKEN&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;Content-Type&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;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`https://myproduct.com/checkout?utm_source=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;domain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;track.mysite.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`promo-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;trackConversion&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="p"&gt;});&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;link&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;platform&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;link&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;shortUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;Then use their webhooks to log conversions:&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;// This fires every time someone clicks your link&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/webhook/dub&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="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&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="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;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&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;event&lt;/span&gt; &lt;span class="o"&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="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;clicks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;insert&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;link&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&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="na"&gt;timestamp&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;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;country&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;country&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;device&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;device&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sendStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&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;Run this once and you never manually create links again. You get a complete audit trail of every click.&lt;/p&gt;

&lt;p&gt;Bitly doesn't offer webhooks at all. Short.io does, but only on paid tiers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Real Cost Calculation
&lt;/h2&gt;

&lt;p&gt;Let's say you run 10 campaigns per year and use the tools for 5 years.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Bitly ($35/month):&lt;/strong&gt; 10 campaigns × 5 years × $35/month × 12 = &lt;strong&gt;$21,000&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Short.io ($25/month):&lt;/strong&gt; 10 campaigns × 5 years × $25/month × 12 = &lt;strong&gt;$15,000&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Dub.co&lt;/a&gt; (Free):&lt;/strong&gt; &lt;strong&gt;$0&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's not an exaggeration. That's the actual pricing difference. Even if Dub.co charged $10/month, it would be a better deal than Bitly.&lt;/p&gt;

&lt;p&gt;But Dub.co doesn't charge. Custom domains, full analytics, API, webhooks, branded QR codes—all free. The paid tier ($12/month) is for teams that need advanced permissions and priority support, which is genuinely useful if you have 50+ links.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters for Conversion Tracking
&lt;/h2&gt;

&lt;p&gt;Marketers who care about conversions obsess over attribution. Which email subject line drove sales? Which ad platform paid off? Which traffic source is worth more?&lt;/p&gt;

&lt;p&gt;Link analytics are the first step. They show you which links got clicks. Then you build from there—adding conversion pixels, utm parameters, and downstream tracking.&lt;/p&gt;

&lt;p&gt;Dub.co makes this easier than competitors because:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Custom domains feel professional&lt;/strong&gt; (customers don't see "bitly.com")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Full API access means you automate everything&lt;/strong&gt; (no manual link creation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Webhooks let you build custom tracking workflows&lt;/strong&gt; (log clicks to your own database)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Free tier doesn't compromise core features&lt;/strong&gt; (no "upgrade to see your data" games)&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Verdict
&lt;/h2&gt;

&lt;p&gt;If you're paying for Bitly or Short.io, switch. If you're not tracking your links at all, start now.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dub.sh/cfN8nzW" rel="noopener noreferrer"&gt;Try Dub.co free&lt;/a&gt; (yes, the affiliate link is real—I use it myself and genuinely recommend it).&lt;/p&gt;

&lt;p&gt;Set up a custom domain, create a link, install their snippet, and watch real-time analytics populate. It takes 10 minutes. No credit card required.&lt;/p&gt;

&lt;p&gt;Then use the API to build whatever you need. Link expiration? Rotation? A/B testing links? Conversion goals? All possible. All free.&lt;/p&gt;

&lt;p&gt;That's link analytics that actually make sense.&lt;/p&gt;

</description>
      <category>analytics</category>
      <category>marketing</category>
      <category>webdev</category>
      <category>tools</category>
    </item>
  </channel>
</rss>
