Conversion & analytics13 min read
Store all of an image's or video's hotspots in one JSON post meta row on the media file, with x and y as percentages of its width and height, and render them as positioned HTML details elements. Percentages keep each hotspot on the same point at any screen size; in our test they were within 0.01% of the stored point at 390 px and 1280 px wide. Load every tagged product with one wc_get_products() call: for 12 hotspots that took 14 database queries on a cold cache, against 42 when each hotspot loaded its own product. Products that are deleted, drafted or hidden since they were tagged simply don't appear. On phones, the product card opens as a bottom sheet so it never covers the other hotspots. A SaaS platform such as Taggbox is the better choice when the content is customer photos and social posts rather than your own catalog shots.
Conversion & analytics16 min read
A shoppable video widget hurts Core Web Vitals in two ways. If its box has no height until the widget loads, it pushes the page down (CLS). And if it autoplays a preview, it spends the shopper's bandwidth on video before they've asked for it. In our test on a throttled phone profile, an iframe widget without reserved space scored a CLS of 0.069 on every run and downloaded about 3.3 MB of video in the first seven seconds. Giving the same widget a CSS-sized slot brought CLS to 0, but it still downloaded the video. A small web component that reserves its height in CSS, fetches a JSON feed only when the rail nears the screen, and creates the video element only on tap had a CLS of 0, downloaded no video before a tap, and loaded 284 KB in total. If you use a hosted platform such as Tolstoy for tagging, analytics and UGC collection, give its widget a fixed-height slot and inject its script when that slot approaches the viewport.
Conversion & analytics14 min read
You don't have to choose between them. Prerender every variation as its own static page (app/pdp/[variant]/[handle], with generateStaticParams and revalidate), and let Next.js's proxy (called middleware before Next.js 16) pick the variation per visitor and rewrite /products/mug to /pdp/b/mug. The page stays static, there's no client-side swap and no flicker. Ask VWO's SDK once per visitor and keep the answer in a cookie: getFlag() sends an impression every time it's called, and the proxy can't tell a prefetch from a page view. Create one VWO client per server and reuse it: init() downloads the settings file, which cost 158 ms per request in our test against 0.4 ms for a shared client. Two production traps we hit: the rewritten response still says s-maxage=3600 under the public URL, so a URL-keyed CDN would serve one variant to everyone, and Next.js runs the proxy again for the rewritten path if the matcher covers it. VWO (now part of Wingify) is our pick.
Conversion & analytics12 min read
A JavaScript review widget puts your Google reviews in an iframe, not in your product page: with EmbedSocial's own demo widget, none of the review text was in the server HTML or the page's own document, and the widget added 965 KB over 25 third-party requests (scripts for YouTube and Vimeo, avatars and EmbedSocial's frame). Reading the same content from the EmbedSocial API on the server and printing it as HTML adds 1.6 KB of markup and only lazy-loaded images. Cache it in a WordPress transient, keep a last-good copy in an option, and refresh it in WP-Cron so no shopper ever waits for the API. Show the newest reviews whatever their rating, label them as reviews of the store, and keep them out of structured data: Google Business reviews are about your business, not the product, and Google's rules say not to aggregate ratings from other websites. The product's AggregateRating should come only from WooCommerce's own product reviews. EmbedSocial is our pick (its API is on the Premium plan); Taggbox is a strong alternative for shoppable UGC galleries.
Conversion & analytics14 min read
A KPI dashboard that managers trust needs one row of numbers per day, built the same way every day, from WooCommerce orders, Stripe subscriptions and Search Console. A Python script on cron can pull all three APIs, join them on customer email and write the row to a Google Sheet for free. It's the only way to get cross-source metrics such as LTV that includes store purchases, but you own every token, API change and silent failure. Databox connects WooCommerce, Stripe and Search Console natively, syncs hourly on paid plans, and adds goals, alerts and scheduled reports, so day-to-day maintenance drops to near zero. The best setup combines them: Databox's connectors for standard metrics, plus a small nightly script that pushes the custom metrics (MRR, 30-day churn, LTV, subscriber store revenue) into a Databox dataset through its v2 API. Our tested script does both, rewrites the last four days because Search Console data arrives late, and can write the same rows to Google Sheets. Databox is our pick; Metabase and Grafana are the open-source alternatives if you'd rather host it yourself.
Conversion & analytics15 min read
Shopify records every online store search with a search_results_were_returned flag, and since Admin API 2025-10 you can query it with ShopifyQL (FROM searches, read_reports scope). Pull the zero-result queries monthly, compare their words against your catalog's own vocabulary, and sort them: typos and missing synonyms go into the Search & Discovery app, combinations need merchandising, true gaps are a stocking or redirect decision. The script in this guide does the sorting and publishes reviewed redirects to a shop metafield your theme reads. If you'd rather not maintain that loop, Searchanise handles synonyms, typo suggestions, search redirects and no-result analytics as one app, from $16 a month billed yearly for up to 1,500 products.
Conversion & analytics4 min read
Browser pixels now miss many conversions because of Apple's App Tracking Transparency, Safari's cookie limits, link-parameter stripping and ad blockers. Server-side tracking sends the same purchase events from your store's server through Meta's Conversions API or TikTok's Events API, with hashed customer data and a shared event ID to prevent double counting.