Popup and Email Capture Apps on Shopify, Ranked by JavaScript Weight
Klaviyo, Privy, Justuno, OptinMonster, Poptin weighed in kilobytes and measured in INP impact. Which ones lazy-load properly and which fire on every page regardless of intent.
Every Shopify storefront we audit arrives with at least one popup app bolted on, and in most cases the app is doing three things the merchant never asked for. It is loading on pages where no campaign will ever display. It is running its targeting logic in the browser after shipping the full bundle. It is adding tens to hundreds of kilobytes of parse cost to the interaction that matters most on mobile, which is the first tap. This piece weighs the five popup and email capture tools that dominate the Shopify App Store by install base, Klaviyo, Privy, Justuno, OptinMonster and Poptin, and ranks them by the only metric that shows up in Core Web Vitals, the JavaScript they put on the main thread.
The measurements come from a clean Dawn 15 install with a single signup form configured per tool, no extra campaigns, and a standard three-route walk from home to collection to product. Network transfer is captured gzipped over the wire, parse cost is captured uncompressed the way V8 sees it, and interaction latency is sampled on a mid-tier Android profile while the popup listeners are armed but the popup itself has not yet revealed. The numbers in this article are reference figures rather than laboratory absolutes, because every merchant changes them the moment they add campaigns, audiences and custom CSS. What does not change is the shape of each app's loading behaviour, and that shape is what the ranking actually captures.
The Diagnostic Nobody Runs: Does The App Fire On Every Page
Before any kilobyte discussion, the single most useful test is the one most merchants skip. Open DevTools, clear the network tab, disable the cache, and walk from home to a collection page to a product page without triggering the popup. Filter the network panel by the app's domain. If the primary bundle reappears on every route, or if the performance profile shows Evaluate Script firing against the same vendor file on each navigation, the app is shipping weight to pages that will never display anything to the shopper. Four of the five tools in this article do exactly that. The single exception, OptinMonster, evaluates targeting rules at its own CDN edge and only ships the campaign payloads that could actually trigger on the current URL, which is why its delivered cost on a typical storefront is a fraction of what its competitors charge.
This matters because popup targeting is usually intent-shaped. Exit intent on a cart page. Scroll depth on a long-form product. First-visit offer on the home route. None of these apply to a shopper deep-linked onto a PDP via paid social, yet the bundles arrive anyway. The weight is paid, the INP tax is paid, and no popup ever shows. A merchant running Privy with a single abandoned-cart campaign is loading the full widget on every PDP view purely so the browser can read the URL and decide not to display anything. The decision could have been made on the server. It was not.
Klaviyo: The Default Answer, And Why Its Weight Is Structural
Klaviyo is the email system of record for most serious Shopify merchants, and its onsite script usually arrives as a package deal with the account. The tracker file alone weighs in around 38 KB gzipped, which parses to roughly 118 KB on the main thread. That is the light part. As soon as a signup form is configured in the dashboard, a forms bundle joins the party, another 55 to 70 KB gzipped, parsing at close to 180 KB. Both load on every page of the storefront whether or not a form is configured to appear there. Form HTML is injected by JavaScript, so there is no server-rendered fallback for shoppers on slow connections or those whose browsers block the script.
The INP picture depends on what else is happening on the page. On a homepage hero the forms bundle often parses during LCP image decode, which is fine, the bytes are overlapped with idle decode work. On a collection page with forty product cards the overlap turns into contention, and we see first-tap latency on the filter menu climb into the 280 to 420ms range on mid-tier Android profiles. That is not a Klaviyo bug, it is the consequence of shipping 300 KB of parsed JavaScript to a page that already has a lot to do. Klaviyo is not alone in this behaviour, but because it is so widely installed it is the one that shows up in merchant field data most often.
The quiet secret of Klaviyo is that none of its front-end weight is required to capture an email. Klaviyo's own API exposes a client subscription endpoint that accepts an email, a consent record and a list identifier and creates the profile server-side. A Shopify App Proxy route can call that endpoint from behind the storefront domain, which means a plain native form with a standard submit handler can enrol a shopper into exactly the same list without loading a single byte of Klaviyo front-end code. The flows still fire, the profile still merges with order events through the web-pixel integration, and the subscriber experience downstream is identical. The only thing that disappears is the JavaScript on the critical path.
Privy: The Acquired Widget That Still Loads Everywhere
Privy, now owned by Attentive, remains one of the most installed popup tools on Shopify and its loading pattern is the textbook example of client-side targeting. The main widget weighs about 62 KB gzipped, parses to nearly 195 KB, and brings along a campaigns bundle of another 45 KB that contains display logic for every campaign in the account. Targeting filters, which URL a campaign should display on, which audience segment it applies to, which device type, all of these evaluate in the browser after the bundle arrives. A merchant with a single cart-abandon campaign and nothing else will ship the full payload on every PDP view, every collection view, every blog route, every 404.
Animation is the second INP culprit. Privy's reveal logic reads offsetHeight before writing inline styles, a classic layout thrash pattern that forces the browser to reconcile layout twice per mount. On mid-tier Android we see 90 to 160ms of INP contribution on the frame where the popup shows, which in isolation is tolerable, but it lands on top of whatever the theme is already doing. Privy is not the heaviest app on this list by parse cost, but it is the clearest offender on the "fires on every page regardless of intent" pattern, because there is no server-side gating at all.
Justuno: The Heaviest Parse, And A Scroll Listener Problem
Justuno is the weight leader of the group and it gets there through a chain-loaded architecture. The loader itself is tiny, around 8 KB, but it immediately pulls in an embed bundle of roughly 78 KB gzipped which parses to about 240 KB, plus a separate rules engine of another 35 KB. All of this runs in the browser regardless of whether the current page is a target for any campaign.
The more specific Justuno problem is a scroll listener attached with passive: false for the mobile exit-intent heuristic, which synthesises an exit event from upward scroll velocity. Non-passive scroll listeners block the compositor from scrolling independently, which shows up as janky scroll on any device with a meaningful content length. Merchants who notice scroll stutter on long collection pages and cannot find the cause in their theme should check the Justuno bundle first. The INP cost on scroll-initiated interactions is measurable and unusual for a popup tool, because popup tools are not supposed to intercede in scroll at all.
OptinMonster: The Quiet Outlier With Server-Side Decisioning
OptinMonster ships a thin API file, around 14 KB gzipped, and a campaign payload that is shaped on the server before it leaves the CDN. The edge evaluates audience rules, URL targeting, referrer conditions and visitor history, then sends down only the campaigns that are eligible to display on the current page view. Each active campaign arrives as its own small bundle of 25 to 40 KB. On a storefront with one active exit-intent campaign the total delivered cost is roughly 45 KB gzipped, which is less than Privy's targeting bundle alone, and the remainder of the storefront pays close to nothing.
This is not a marketing claim, it is visible in the network waterfall. Walk from home to a blog post on a site running OptinMonster and you will see the API file request on both routes, but the campaign payload will only appear on the routes that match its conditions. The mount still costs 40 to 80ms of main-thread time because the shadow DOM has to be built and the campaign has to be rendered, but the bytes per page view are low, and more importantly the bytes per page view that cannot possibly fire are zero. For merchants who have decided they want a third-party popup rather than a native form, OptinMonster is the least damaging choice from a performance standpoint.
Poptin: Light But Sloppy Around Triggers
Poptin sits between OptinMonster and the rest on transfer size, around 28 KB gzipped and 88 KB parsed, and it loads on every page. The trigger system is the notable weakness. Every configured trigger, exit, scroll depth, timer, inactivity, is registered as its own listener at mount, and the inactivity timer uses a 250ms setInterval which produces visible long tasks in a performance trace. Individually each listener is cheap. Collectively they add background work to pages that may never fire the popup, and the cost compounds when other apps are present, which is usually the case on mature Shopify stores.
INP on the reveal frame runs in the 60 to 110ms range, which is the best of the always-loaded set, and the campaign targeting is still client-side. Poptin is a reasonable choice for merchants who want a minimum viable popup without Klaviyo's marketing-suite gravity, and its weight is survivable, but it is not intent-gated in any meaningful sense.
The Ranking And What It Actually Means
Lined up by delivered weight on a representative storefront with one active campaign, OptinMonster leads at roughly 45 KB, Poptin follows at 28 KB of always-loaded code, Klaviyo lands at 93 to 108 KB depending on whether the forms bundle has been dashed in, Privy arrives at 107 KB, and Justuno tops the scale at 121 KB. The rankings invert slightly if a merchant runs Klaviyo without an active form, because the tracker alone is lighter than Privy's widget, but the moment an email form is configured Klaviyo rejoins the pack.
Weight is not the whole story. OptinMonster is genuinely lazy in the sense that matters, bytes per page view scale with eligible campaigns rather than with campaigns configured in the account. Poptin is light but bad at trigger cleanup. Klaviyo is heavy but replaceable with server-side capture. Privy is heavy and fully client-gated. Justuno is heaviest and adds a scroll-listener penalty on top of its parse cost. The practical reading is that the ranking by weight and the ranking by damage are not the same ranking, and any merchant making a decision based purely on App Store screenshots is missing the behaviour that shows up in field data.
The Intent-Gated Native Form Alternative
The engineering answer most merchants never consider is that the popup is a rendering concern and the subscription is an API concern, and the two do not have to be solved by the same vendor. A Shopify section can render a native HTML form with a plain email input. An IntersectionObserver four lines long can decide to reveal it when the shopper scrolls past a specific point. A mouseleave listener on the document root can replicate exit intent on desktop without any third-party code. On submit, the form POSTs to a Shopify App Proxy route, which forwards the email and consent metadata to Klaviyo's profile subscription API server-side. The profile appears in the correct list, the welcome flow fires, the order events still associate through Klaviyo's web pixel, and the shopper never downloaded a single byte of Klaviyo front-end bundle to participate.
The same pattern works with Mailchimp, with Omnisend, with Attentive's SMS API, with any provider that exposes server-side profile creation. It takes an afternoon to build and it removes the single largest third-party JavaScript dependency from most Shopify storefronts. The trade-off is that the built-in drag-and-drop campaign editor disappears, which matters if marketing ownership sits with a non-technical team, and it genuinely matters when a merchant runs dozens of concurrent campaigns with frequent creative rotation. For the far more common case, one welcome offer and one exit-intent discount, the native route is lighter, faster and more accessible.
This is the audit WitsCode runs on every engagement that involves popups. We measure the existing bundle weight, identify which pages are paying cost for campaigns they cannot display, and either configure server-side gating where the vendor supports it or replace the popup entirely with an intent-gated native form that posts to the same ESP through its server API. The email list keeps growing. The LCP improves. The INP numbers come back into the green. The marketing team keeps its welcome flow. Nothing about the shopper experience gets worse, and the storefront stops paying a performance tax on pages where no popup was ever going to show.
The right popup app for a Shopify storefront is the one that ships the fewest kilobytes to the pages where it will not appear. By that standard the field is small. OptinMonster is the only one of the five that takes server-side gating seriously. Everyone else is an audit candidate, and the audit usually ends with a native form.
Get weekly field notes.
Practical writing on shipping products, straight to your inbox. No spam.
Need help with this?
Shopify Development
We design and build web apps, MVPs, and SaaS products. Talk to us about what you are working on.
Talk to usWant to discuss ecom for your business?
Start a project and we'll talk through where you are, what's working, and the highest-leverage moves for the next 90 days.

