<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aymane</title>
    <description>The latest articles on DEV Community by Aymane (@aymaneonlinedev).</description>
    <link>https://dev.to/aymaneonlinedev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4170668%2F2b95680d-b3f9-4c78-bde1-68c7747be91c.jpg</url>
      <title>DEV Community: Aymane</title>
      <link>https://dev.to/aymaneonlinedev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aymaneonlinedev"/>
    <language>en</language>
    <item>
      <title>Waitlist Benchmarks: Conversion, Referral &amp; Email Rates (2026)</title>
      <dc:creator>Aymane</dc:creator>
      <pubDate>Fri, 09 Oct 2026 07:30:12 +0000</pubDate>
      <link>https://dev.to/aymaneonlinedev/waitlist-benchmarks-conversion-referral-email-rates-2026-hbm</link>
      <guid>https://dev.to/aymaneonlinedev/waitlist-benchmarks-conversion-referral-email-rates-2026-hbm</guid>
      <description>&lt;p&gt;"How many signups should my waitlist get?" is the wrong question until you know what good looks like. This page collects the formulas behind the numbers and the benchmark ranges to aim for — so you can set targets that hold up instead of guessing.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: figures below come from public benchmark reports and vendor studies, cited inline. Your results will depend on your audience and page. Use these as orientation, not guarantees. The formulas are exact; plug in your own data.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Waitlist conversion rate: the formula
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Conversion rate = signups ÷ unique visitors × 100.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the number to watch first. It isolates whether your page and offer connect, separate from how much traffic you send. If you drive 1,000 visitors and get 30 signups, your conversion rate is 3%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is a good range?&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Conversion rate&lt;/th&gt;
&lt;th&gt;What it usually means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Under 5%&lt;/td&gt;
&lt;td&gt;The page, offer, or traffic is off — fix these before scaling&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5–10%&lt;/td&gt;
&lt;td&gt;Typical for an average landing page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10%+&lt;/td&gt;
&lt;td&gt;Strong; a well-run waitlist&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;20%+&lt;/td&gt;
&lt;td&gt;Excellent, usually with warm or targeted traffic&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For context, Unbounce's conversion benchmark report — analyzing roughly 57 million conversions across more than 41,000 landing pages — puts the &lt;strong&gt;median landing page conversion rate at about 6.6%&lt;/strong&gt;. Waitlister's analysis of thousands of waitlists reports a &lt;strong&gt;median waitlist conversion rate around 11%&lt;/strong&gt;, suggesting a focused waitlist page out-converts a generic landing page. Treat both as directional, not targets to beat.&lt;/p&gt;

&lt;p&gt;If your traffic is cold (ads, broad social), expect the lower end; if it is warm (your followers, a community, referrals), expect higher.&lt;/p&gt;

&lt;p&gt;Related: &lt;a href="https://getwaitly.com/blog/waitlist-page-copywriting" rel="noopener noreferrer"&gt;Waitlist Copywriting that Converts&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referral k-factor (viral coefficient)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;k = i × c&lt;/strong&gt;, where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;i&lt;/code&gt; = average invites sent per subscriber&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;c&lt;/code&gt; = conversion rate of those invites (invites that become signups)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Worked example:&lt;/strong&gt; if 100 subscribers each send 3 invites on average (&lt;code&gt;i = 3&lt;/code&gt;) and 15% of invites convert (&lt;code&gt;c = 0.15&lt;/code&gt;), then k = 3 × 0.15 = &lt;strong&gt;0.45&lt;/strong&gt;. Those 100 subscribers bring in about 45 more. Growth still depends on new traffic — the loop slows down.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;To get k above 1&lt;/strong&gt; (self-sustaining growth), you need the product of the two numbers above 1. For example, 4 invites per subscriber at 25% conversion gives k = 1.0; 5 invites at 25% gives k = 1.25.&lt;/p&gt;

&lt;p&gt;Two levers raise k: make sharing easier (more invites) and make the reward compelling (higher conversion). Only about &lt;strong&gt;7% of waitlists run a referral program at all&lt;/strong&gt;, per Waitlister's analysis — so simply turning on referrals puts you ahead of most.&lt;/p&gt;

&lt;p&gt;Related: &lt;a href="https://getwaitly.com/blog/pre-launch-referral-program-guide" rel="noopener noreferrer"&gt;Pre-Launch Referral Program Guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Referral rate and referral conversion
&lt;/h2&gt;

&lt;p&gt;Two different metrics are often confused:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Referral rate = subscribers who referred at least one person ÷ total subscribers.&lt;/strong&gt; This measures how many people share at all. A healthy program gets a meaningful share of subscribers to refer; if almost nobody shares, the reward or the friction is the problem.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Referral conversion rate = signups from referral links ÷ clicks on referral links.&lt;/strong&gt; This measures the quality of referred traffic. Referred visitors often convert better than cold traffic because the recommendation comes from a friend.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Track both. A high referral rate with low conversion means people are sharing to a cold audience; a low referral rate with high conversion means the reward is good but hard to find.&lt;/p&gt;

&lt;p&gt;Related: &lt;a href="https://getwaitly.com/blog/pre-launch-referral-program-guide" rel="noopener noreferrer"&gt;Pre-Launch Referral Program Guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Email open and click rates
&lt;/h2&gt;

&lt;p&gt;Once you can email your list, three formulas matter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Open rate = opens ÷ emails delivered.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Click rate = clicks ÷ emails delivered.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click-to-open rate (CTOR) = clicks ÷ opens.&lt;/strong&gt; This tells you whether the people who opened found the content worth clicking.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Email benchmarks vary widely by list, industry, and send frequency. For an engaged pre-launch list, open rates are often reported in the &lt;strong&gt;20–40% range&lt;/strong&gt;, with click rates of a few percent. A dropping open rate is the earliest warning that your audience is losing interest — tighten your sending, and email only when you have something worth saying.&lt;/p&gt;

&lt;p&gt;Related: &lt;a href="https://getwaitly.com/blog/waitlist-email-sequence-guide" rel="noopener noreferrer"&gt;Waitlist Email Sequence Guide&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Launch-day conversion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Launch conversion = paying customers ÷ waitlist size.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the number people brag about, and the one with the widest spread. It depends almost entirely on product, price, and how warm the waitlist is — not on the waitlist tool. Expect a range rather than a fixed target, and watch the trend across launches rather than one data point.&lt;/p&gt;

&lt;p&gt;Related: &lt;a href="https://getwaitly.com/blog/launch-day-playbook" rel="noopener noreferrer"&gt;Launch Day Playbook&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to set targets that hold up
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Start with your conversion rate.&lt;/strong&gt; If it is under 5%, do not scale traffic yet — improve the page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Add a referral loop.&lt;/strong&gt; Even a simple milestone ("invite 3 friends for early access") raises your referral rate from zero, and word-of-mouth remains the most trusted channel (Nielsen puts word-of-mouth trust around 88%).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Protect deliverability.&lt;/strong&gt; Double opt-in and a clean list keep your launch email out of spam.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compare against yourself.&lt;/strong&gt; Your own last 30 days are a better benchmark than any industry average.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The point of benchmarks is not to hit a number — it is to know which number to fix next.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is a good waitlist conversion rate?
&lt;/h3&gt;

&lt;p&gt;A median landing page converts around 6.6% (Unbounce's benchmark report), while waitlist-specific analyses report a median closer to 11%. Anything above 10% is strong; under 5% usually signals a page or traffic problem worth fixing first.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is the formula for the viral coefficient (k-factor)?
&lt;/h3&gt;

&lt;p&gt;k = i × c, where i is the average number of invites per subscriber and c is the conversion rate of those invites. k above 1 means self-sustaining growth; below 1 means growth relies on new traffic.&lt;/p&gt;

&lt;h3&gt;
  
  
  How many people on a waitlist actually refer?
&lt;/h3&gt;

&lt;p&gt;Only about 7% of waitlists run a referral program, according to Waitlister's analysis, so a large share of list owners never measure this. Among those that do, referral rate (percent of subscribers who refer at least one person) is the metric to track.&lt;/p&gt;

&lt;h3&gt;
  
  
  What email open rate should I expect?
&lt;/h3&gt;

&lt;p&gt;For an engaged pre-launch list, open rates commonly fall in the 20–40% range, with click rates of a few percent. Both vary by list and send frequency, so watch your own trend over time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where do these benchmark numbers come from?
&lt;/h3&gt;

&lt;p&gt;The conversion figures are cited from Unbounce's conversion benchmark report and Waitlister's published waitlist analysis. The formulas are standard. All figures are directional — use your own data for decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related guides
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://getwaitly.com/blog/waitlist-glossary" rel="noopener noreferrer"&gt;Waitlist Glossary: 16 Terms Every Founder Should Know&lt;/a&gt; — plain-English definitions for every term here&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://getwaitly.com/blog/pre-launch-referral-program-guide" rel="noopener noreferrer"&gt;Pre-Launch Referral Program Guide&lt;/a&gt; — raising your referral rate and k-factor&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://getwaitly.com/blog/waitlist-page-copywriting" rel="noopener noreferrer"&gt;Waitlist Copywriting that Converts&lt;/a&gt; — lifting your conversion rate&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://getwaitly.com/blog/waitlist-email-sequence-guide" rel="noopener noreferrer"&gt;Waitlist Email Sequence Guide&lt;/a&gt; — the emails behind the open and click rates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The simple, affordable waitlist tool for founders and makers. Start free in 5 minutes — no credit card required. &lt;a href="https://getwaitly.com/signup" rel="noopener noreferrer"&gt;Try GetWaitly free →&lt;/a&gt;&lt;/p&gt;

</description>
      <category>saas</category>
      <category>webdev</category>
      <category>analytics</category>
      <category>marketing</category>
    </item>
    <item>
      <title>How to Add a Waitlist to React &amp; Next.js</title>
      <dc:creator>Aymane</dc:creator>
      <pubDate>Thu, 08 Oct 2026 08:53:11 +0000</pubDate>
      <link>https://dev.to/aymaneonlinedev/how-to-add-a-waitlist-to-react-nextjs-5fci</link>
      <guid>https://dev.to/aymaneonlinedev/how-to-add-a-waitlist-to-react-nextjs-5fci</guid>
      <description>&lt;p&gt;If you are building your pre-launch site in React or Next.js, you do not need a waitlist SDK or npm package. GetWaitly ships a single script tag and a container element — the same embed that works on any site. Here is how to wire it into a React or Next.js app cleanly.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short answer
&lt;/h2&gt;

&lt;p&gt;Load &lt;code&gt;https://getwaitly.com/widget.js&lt;/code&gt; once in your root layout, then render a &lt;code&gt;&amp;lt;div className="gw-widget" data-waitlist-id="YOUR_WAITLIST_ID" /&amp;gt;&lt;/code&gt; wherever the form should appear. For a popup, render a &lt;code&gt;&amp;lt;button className="gw-trigger" data-waitlist-id="YOUR_WAITLIST_ID"&amp;gt;&lt;/code&gt;. Use the waitlist's public &lt;strong&gt;ID&lt;/strong&gt;, not its slug. Total time: 5 minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you need
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A GetWaitly account with a waitlist created (free plan covers 100 subscribers).&lt;/li&gt;
&lt;li&gt;Your waitlist's public ID from the Widget/Embed section of the dashboard.&lt;/li&gt;
&lt;li&gt;A React or Next.js app. The widget is plain JavaScript — it does not care which framework you use.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The embed, in framework terms
&lt;/h2&gt;

&lt;p&gt;The GetWaitly widget is two parts: a script that defines the &lt;code&gt;&amp;lt;div class="gw-widget"&amp;gt;&lt;/code&gt; behavior, and the div itself. In JSX:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"gw-widget"&lt;/span&gt; &lt;span class="na"&gt;data-waitlist-id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"YOUR_WAITLIST_ID"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script must load once per page. In Next.js that is &lt;code&gt;next/script&lt;/code&gt;; in plain React you can put it in &lt;code&gt;index.html&lt;/code&gt; or inject it in an effect. The widget finds the &lt;code&gt;.gw-widget&lt;/code&gt; element and renders the form into it, styled with your waitlist branding.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js (App Router)
&lt;/h2&gt;

&lt;p&gt;Load the script in your root layout so it is present on every route, and render the widget on the page that needs it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;app/layout.tsx&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Script&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/script&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&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="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Script&lt;/span&gt;
          &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://getwaitly.com/widget.js"&lt;/span&gt;
          &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"afterInteractive"&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;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;&lt;code&gt;app/page.tsx&lt;/code&gt;&lt;/strong&gt; (or any page)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Home&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Something great is coming.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"gw-widget"&lt;/span&gt; &lt;span class="na"&gt;data-waitlist-id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"YOUR_WAITLIST_ID"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;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;code&gt;strategy="afterInteractive"&lt;/code&gt; loads the script after the page becomes interactive, so it does not block your render.&lt;/p&gt;

&lt;h2&gt;
  
  
  Next.js (Pages Router)
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;_app.tsx&lt;/code&gt; to load the script once, and place the div in your page:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;pages/_app.tsx&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Script&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next/script&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AppProps&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="s2"&gt;next/app&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pageProps&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;AppProps&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;pageProps&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Script&lt;/span&gt;
        &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://getwaitly.com/widget.js"&lt;/span&gt;
        &lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"afterInteractive"&lt;/span&gt;
      &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;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;
  
  
  Plain React (Vite / Create React App)
&lt;/h2&gt;

&lt;p&gt;There is no &lt;code&gt;next/script&lt;/code&gt;, so add the script tag to &lt;code&gt;index.html&lt;/code&gt; before the closing &lt;code&gt;&amp;lt;/body&amp;gt;&lt;/code&gt;, and render the div in a component:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;index.html&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://getwaitly.com/widget.js"&lt;/span&gt; &lt;span class="na"&gt;defer&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;src/App.tsx&lt;/code&gt;&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Join the waitlist&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"gw-widget"&lt;/span&gt; &lt;span class="na"&gt;data-waitlist-id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"YOUR_WAITLIST_ID"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;main&lt;/span&gt;&lt;span class="p"&gt;&amp;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;If you cannot edit &lt;code&gt;index.html&lt;/code&gt;, inject the script in an effect instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&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="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;useEffect&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;script[src="https://getwaitly.com/widget.js"]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&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;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;script&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;src&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://getwaitly.com/widget.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;defer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;appendChild&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The popup variant
&lt;/h2&gt;

&lt;p&gt;For a button that opens the form in a modal, load the script once (above) and render a trigger button:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"gw-trigger"&lt;/span&gt; &lt;span class="na"&gt;data-waitlist-id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"YOUR_WAITLIST_ID"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  Join waitlist
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  TypeScript and custom fields
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;data-waitlist-id&lt;/code&gt; is a valid &lt;code&gt;data-*&lt;/code&gt; attribute on a &lt;code&gt;div&lt;/code&gt; and &lt;code&gt;button&lt;/code&gt; in JSX, no type changes needed. Enable name, phone, or custom fields in your GetWaitly widget settings and the form renders them automatically.&lt;/p&gt;

&lt;h2&gt;
  
  
  Single-page apps: one caveat
&lt;/h2&gt;

&lt;p&gt;The widget script initializes on page load. In a single-page app the script loads once and does not re-run on client-side navigation. In practice this is fine because the widget renders into the &lt;code&gt;.gw-widget&lt;/code&gt; div wherever it appears. If you mount the div conditionally &lt;em&gt;after&lt;/em&gt; the script has loaded, the widget may miss it on the first client-side transition — a full page load fixes it. If that matters for your flow, keep the container div mounted, or drive the form yourself with the no-JavaScript form action below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Full control: post to the join endpoint
&lt;/h2&gt;

&lt;p&gt;If you would rather build your own React form (for custom validation or styling), skip the widget script and POST to your waitlist's join endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"https://getwaitly.com/api/join/YOUR_WAITLIST_ID"&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"post"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="na"&gt;required&lt;/span&gt; &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Your email"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Join the waitlist&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The browser posts the signup and redirects to your thank-you page. You lose the inline success animation and the automatic branding, but you keep full control of the markup.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;Run your app, open the page, and submit a test email. Confirm the success message appears and the subscriber lands in your GetWaitly dashboard. If the form does not render, check the browser console for a blocked script (ad blockers and strict CSP can block third-party scripts) and verify the &lt;code&gt;data-waitlist-id&lt;/code&gt; exactly matches your waitlist.&lt;/p&gt;

&lt;h2&gt;
  
  
  FAQ
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is there an npm package for the GetWaitly widget?
&lt;/h3&gt;

&lt;p&gt;No. You inject one script tag (&lt;code&gt;https://getwaitly.com/widget.js&lt;/code&gt;) and render a container div. There is nothing to install.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does GetWaitly work with Next.js Server Components?
&lt;/h3&gt;

&lt;p&gt;Yes — the script loads via &lt;code&gt;next/script&lt;/code&gt; in your layout, and the container div is a plain element you can render from a Server Component. If you add the script in an effect, put that in a Client Component.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why does the widget not render after client-side navigation?
&lt;/h3&gt;

&lt;p&gt;The script initializes on load and does not re-run on route changes. Keep the &lt;code&gt;.gw-widget&lt;/code&gt; div mounted, or use the form action to POST to &lt;code&gt;/api/join&lt;/code&gt; yourself. A hard refresh always re-initializes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I use the popup trigger in React?
&lt;/h3&gt;

&lt;p&gt;Yes. Render a &lt;code&gt;&amp;lt;button className="gw-trigger" data-waitlist-id="YOUR_WAITLIST_ID"&amp;gt;&lt;/code&gt;. Load the script once and any trigger on the page opens the modal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Does it work with Vite, Remix, or Astro?
&lt;/h3&gt;

&lt;p&gt;Yes. Anywhere you can add a &lt;code&gt;&amp;lt;script&amp;gt;&lt;/code&gt; tag and render a div, the widget works. For server-rendered frameworks, load the script with whatever mechanism the framework recommends (or a plain &lt;code&gt;defer&lt;/code&gt; tag).&lt;/p&gt;

&lt;h3&gt;
  
  
  How do I collect custom fields?
&lt;/h3&gt;

&lt;p&gt;Configure them in your GetWaitly widget settings. The inline widget renders the fields you enable. For a fully custom form, use &lt;code&gt;cf_0&lt;/code&gt;, &lt;code&gt;cf_1&lt;/code&gt;, … inputs matched to your custom field order and post to &lt;code&gt;/api/join&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Related guides
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://getwaitly.com/blog/how-to-add-a-waitlist-to-any-website" rel="noopener noreferrer"&gt;How to Add a Waitlist to Any Website&lt;/a&gt; — the generic HTML embed&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://getwaitly.com/blog/how-to-add-a-waitlist-to-framer" rel="noopener noreferrer"&gt;How to Add a Waitlist to Framer&lt;/a&gt; — the Embed component method&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://getwaitly.com/blog/waitlist-form-builders" rel="noopener noreferrer"&gt;Which Form Builder for a Waitlist?&lt;/a&gt; — form builders vs a dedicated waitlist tool&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://getwaitly.com/blog/best-waitlist-tools-solo-founders" rel="noopener noreferrer"&gt;7 Best Waitlist Tools for Solo Founders in 2026&lt;/a&gt; — the full comparison&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The simple, affordable waitlist tool for founders and makers. Start free in 5 minutes — no credit card required. &lt;a href="https://getwaitly.com/signup" rel="noopener noreferrer"&gt;Try GetWaitly free →&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>nextjs</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
