Integrating PostHog A/B Tests with Webflow and Marketing Pages

Teaches you how to wire PostHog experiments into Webflow and other no-code marketing pages so you can run A/B tests on headlines, CTAs, pricing layouts, and onboarding flows without a full development cycle.

Install the PostHog JavaScript snippet in Webflow's project-level custom code settings, then use posthog.onFeatureFlags to read experiment variants and manipulate page elements with vanilla JavaScript. Wrap the page in a hidden state and reveal it only after variant assignment to prevent flicker. This lets you run PostHog Webflow AB tests on landing pages, pricing pages, and onboarding flows without a code deploy or CMS migration.

Outcome: You can launch, measure, and iterate on A/B tests across all your marketing and landing pages without waiting for engineering deploys, while avoiding the visual flicker that undermines user trust and pollutes experiment data.

Synthesized from public framework references and reviewed for accuracy.

ExperienceIntermediate1-2 hours

Prerequisites

  • A PostHog project with the JavaScript Web SDK available
  • Admin or editor access to a Webflow project (or equivalent no-code builder with custom code injection)
  • A PostHog experiment already created with feature flag variants defined
  • Basic comfort reading and writing vanilla JavaScript (DOM manipulation, event listeners)
  • Familiarity with the PostHog feature flag and experiment concepts covered in the parent method

Overview

Most product teams run experiments inside their application code, but some of the highest-leverage tests live on marketing pages: hero headlines, CTA copy, pricing tier layouts, sign-up form length, and onboarding welcome flows. These pages frequently live in Webflow, Framer, WordPress, or another no-code builder that sits outside the main application codebase. Getting PostHog experiments running on those pages requires a different integration pattern than the standard React or Next.js SDK. This skill covers that pattern end to end, from snippet installation through variant rendering and anti-flicker handling, specifically for PostHog Webflow AB tests and similar no-code environments.

Within the PostHog Experiments Onboarding A/B Test Method, this skill fills a critical gap. The method assumes you can assign users to variants and display different experiences. On a server-rendered or React app, the SDK handles that natively. On a Webflow marketing page, you need to manually load the PostHog JavaScript snippet, listen for feature flag evaluation, manipulate the DOM to show the correct variant, and prevent the default content from flashing before the variant loads. Without this skill, teams either skip testing their highest-traffic pages or resort to third-party tools like Google Optimize (now deprecated) or VWO, fragmenting their experimentation data across platforms.

The concrete artifact you produce is a working Webflow page (or set of pages) with PostHog experiment code injected via custom code blocks. The page loads, assigns the visitor to a variant using PostHog's feature flag infrastructure, renders the correct experience with no visible flicker, and fires the appropriate PostHog events so your experiment dashboard tracks conversions accurately. You also get a reusable code template you can copy across future landing page tests, cutting setup time for subsequent experiments from hours to minutes.

This skill applies equally to other no-code builders that support custom code injection. The examples focus on Webflow because it is the most common marketing-page builder among teams already using PostHog, but the JavaScript patterns work identically in Framer custom code blocks, WordPress header/footer injection plugins, Squarespace code injection, and static HTML pages served from a CDN.

How It Works

The core challenge of running PostHog Webflow AB tests is timing. When a visitor loads a Webflow page, the browser renders the default HTML and CSS immediately. PostHog's JavaScript snippet then loads asynchronously, evaluates the visitor's feature flags, and returns the assigned variant. If you wait for that evaluation before changing the page, the visitor sees the default content flash before the variant appears. This flicker biases your experiment because users notice the shift, and it degrades the perceived quality of your site.

The solution uses a three-phase rendering pattern. Phase one: hide. You inject a small inline style or script at the very top of the page's custom code that sets the page body (or a wrapper element) to opacity: 0 or visibility: hidden. This runs synchronously before any content paints. Phase two: evaluate. The PostHog snippet loads, the library initializes, and your code calls posthog.onFeatureFlags to receive the variant assignment. Phase three: mutate and reveal. Inside the callback, your code reads which variant the user is in, manipulates the DOM accordingly (swapping headlines, showing or hiding sections, changing button text), and then sets the body back to opacity: 1 with a CSS transition. The entire sequence typically completes in 200-600 milliseconds, well within the threshold where users perceive the page as loading normally rather than changing.

This pattern works because PostHog evaluates feature flags client-side using the visitor's distinct ID and the flag's targeting rules. The evaluation does not require a round trip to PostHog's servers on every page load if flags were previously fetched and cached, though the first visit for a new user will involve a network request. The onFeatureFlags callback fires as soon as all flags are resolved, giving you a single reliable hook to branch your rendering logic.

The DOM manipulation itself uses vanilla JavaScript because Webflow pages do not have a framework runtime. You select elements by class name (Webflow assigns readable class names), data attribute, or ID, then toggle visibility, swap innerText or innerHTML, or adjust CSS classes. For experiments that test entirely different page layouts rather than individual elements, a cleaner approach is to build both variants as separate Webflow sections, hide them all by default with a shared CSS class, and then show only the section matching the assigned variant. This avoids complex element-level manipulation and keeps the Webflow designer as the source of truth for both designs.

Within the broader PostHog Experiments Onboarding A/B Test Method, this integration step happens after you have designed your hypothesis (covered in designing experiment hypotheses) and set up your feature flag (covered in setting up feature flags for experiments). It is the implementation layer that connects the experiment definition in PostHog's UI to the actual visitor experience on a page that lives outside your application codebase. Once the integration is live, events flow into the experiment dashboard where you interpret results using Bayesian or frequentist analysis.

Step-by-Step

  1. Step 1: Install the PostHog JavaScript snippet in Webflow

    Open your Webflow project settings, navigate to the Custom Code tab, and paste your PostHog JavaScript snippet into the "Head Code" section. The snippet should call posthog.init() with your project API key and the PostHog host URL. Placing it in the Head Code section ensures it loads on every page of your Webflow project, not just a single page. After pasting, publish your Webflow site so the snippet goes live.

    Verify installation by opening your published site in a browser, opening DevTools, typing posthog in the console, and confirming the object exists with your API key.

    Tip: If you use a reverse proxy or custom domain for PostHog (e.g., `e.yourdomain.com`), update the `api_host` in the snippet to point there. This avoids ad blockers that target `app.posthog.com` and significantly increases the percentage of visitors who get tracked and assigned to experiments.

  2. Step 2: Create the experiment and feature flag in PostHog

    In the PostHog app, go to Experiments and create a new experiment. Give it a clear name like landing-page-hero-headline-test. Define your variants: control (current headline) and test (new headline), or use more descriptive names like benefit-led and social-proof-led. Set the feature flag key to something readable like landing-hero-experiment.

    Configure your targeting to match the audience you want to test, such as all visitors, or visitors from a specific UTM campaign. Set the rollout percentage to 100% so all matching visitors enter the experiment. Save the experiment but do not launch it yet. You need to deploy the page-side code first to avoid a state where visitors are assigned variants but see no difference.

    Tip: Use the "test" variant value as a simple string like `test` or `variant-b` rather than a complex JSON payload. On Webflow pages, you will read this value with `posthog.getFeatureFlag('flag-key')`, and simple strings are easier to branch on in vanilla JS than parsed objects.

  3. Step 3: Add the anti-flicker inline style

    In Webflow, go to the specific page where the experiment runs (not the project-level settings). Open the page's custom code settings and paste this anti-flicker style into the page Head Code section (Webflow labels it "Inside head tag"):

    <style>.experiment-wrapper { opacity: 0; transition: opacity 0.15s ease; }</style>
    

    Then in the Webflow designer, add a class called experiment-wrapper to the outermost div that contains your testable elements.

    This ensures the content is invisible before PostHog loads. The transition property gives a smooth fade-in rather than a jarring pop when the content reveals. Keep this style inline and in the head so it applies before any external stylesheets or scripts load.

    Tip: Set a fallback timeout that reveals the page after 1500 milliseconds even if PostHog has not responded. This prevents the page from staying blank if PostHog's CDN is slow or blocked. Add this right after the style: `<script>setTimeout(function(){document.querySelector('.experiment-wrapper').style.opacity='1'},1500)</script>`. Users in the timeout path see the control variant, which is the safe default.

  4. Step 4: Write the variant rendering code

    In the same page-level custom code section (Webflow labels it "Before body tag"), add a script block that listens for PostHog's feature flags to resolve and then manipulates the DOM:

    posthog.onFeatureFlags(function () {
      var variant = posthog.getFeatureFlag('landing-hero-experiment');
      if (variant === 'test') {
        var headline = document.querySelector('.hero-heading');
        if (headline) headline.innerText = 'Cut your reporting time by 75%';
      }
      var wrapper = document.querySelector('.experiment-wrapper');
      if (wrapper) wrapper.style.opacity = '1';
    });
    

    Use querySelector or querySelectorAll to find the elements you want to change. For a headline test, find the heading by its Webflow class and update innerText.

    For a CTA button test, find the button and update its text and possibly its href. For a section-swap test, hide the control section and show the test section by toggling a CSS class. Each DOM change should be a single, clear operation.

    Tip: If you are swapping entire sections rather than individual text elements, build both the control and test sections in the Webflow designer, give each a distinguishing class like `variant-control` and `variant-test`, and set `variant-test` to `display: none` in Webflow's style panel. Your experiment script then just toggles display between the two. This keeps both variants visually editable in Webflow.

  5. Step 5: Add conversion event tracking

    Your experiment needs a goal event that PostHog can count. For landing page tests, the most common conversion events are button clicks, form submissions, or page navigations to a sign-up or checkout page. Add event listeners in the same script block:

    document.querySelector('.hero-cta')?.addEventListener('click', function () {
      posthog.capture('hero_cta_clicked', {
        variant: posthog.getFeatureFlag('landing-hero-experiment')
      });
    });
    

    For a form submission, listen to the form's submit event. For navigation-based conversions, you can configure the goal event as a pageview in PostHog's experiment settings rather than adding client-side code. Include the variant value as a property on the event so you can debug and verify that both variants are firing events correctly.

    Tip: Webflow forms redirect to a thank-you page on submission by default. If your conversion event is form submission, either fire the PostHog event on the submit event before the redirect happens, or configure a pageview-based goal in PostHog that triggers when the thank-you page loads. The pageview approach is more reliable because it does not depend on the event firing before the browser navigates away.

  6. Step 6: Test both variants locally before publishing

    Before publishing to production, verify both variants render correctly. PostHog lets you override feature flag values for testing. Run posthog.featureFlags.override({'landing-hero-experiment': 'test'}) to force the test variant, then reload the page. Confirm the correct elements change, the anti-flicker behavior works (no flash of control content), and the conversion event fires in the PostHog Live Events view.

    Then run posthog.featureFlags.override({'landing-hero-experiment': 'control'}) and reload to confirm the control variant displays correctly and its events also fire. Check the live events stream in PostHog to verify that the events arrive with the correct variant property attached.

    Tip: Test on mobile viewport sizes too. Webflow pages often have different element visibility and layout at mobile breakpoints, and your experiment script may need to target different elements or handle responsive behavior. An experiment that works perfectly on desktop but breaks on mobile will produce uninterpretable results because your mobile visitors see a broken experience.

  7. Step 7: Publish the Webflow page and launch the experiment

    Once both variants are verified, publish your Webflow site to push the experiment code to production. Launch the experiment in PostHog. PostHog will start assigning visitors to variants based on a hash of their distinct ID and the flag key, ensuring each visitor sees the same variant on repeat visits. Monitor the experiment dashboard over the first few hours to confirm that both variants are receiving roughly equal traffic (the split should be close to 50/50 unless you configured otherwise). Check the Live Events stream filtered to your goal event to verify conversions are recording for both variants.

    If one variant shows zero events after several hundred visitors, there is likely a bug in the DOM manipulation or event tracking code for that variant.

    Tip: Do not edit the experiment elements in the Webflow designer after launch unless you intend to change the control variant. Webflow publishes overwrite any custom code changes to the DOM, and a designer edit that changes a class name will break your querySelector selectors. If you need to update the control variant's design, update the experiment code simultaneously.

  8. Step 8: Monitor for implementation integrity during the experiment

    Over the first 24-48 hours, check three things. First, verify the traffic split in PostHog's experiment view matches your configured ratio. A skewed split suggests the feature flag is not evaluating correctly, possibly because of a targeting rule mismatch. Second, check that the bounce rate and time-on-page for both variants are within a reasonable range of each other.

    A massive bounce rate increase in one variant could indicate a rendering bug that visitors see but you missed in testing. Third, check the browser console on the live page for JavaScript errors. Load the page in an incognito window (so you get a fresh session), open DevTools, and watch for errors in the console during the first few seconds of page load. Any error in your experiment script could prevent variant rendering or event tracking from working.

    Tip: Set up a PostHog insight that shows daily unique visitors split by the feature flag variant. This gives you an ongoing visual check that both arms are receiving traffic. If the line for one variant drops to zero on a specific day, investigate immediately because something likely broke in a Webflow publish.

Examples

Example: Headline test on a SaaS landing page in Webflow

A B2B SaaS startup with 3,000 weekly landing page visitors wants to test whether a benefit-led headline ('Cut your reporting time by 75%') outperforms their current feature-led headline ('Automated Financial Reporting Platform'). The page is built in Webflow with a custom domain. The team has one marketer and no front-end engineer available.

The marketer installs the PostHog snippet in Webflow's project-level head code and verifies it loads on the landing page by checking the browser console. In PostHog, they create an experiment named landing-hero-headline-q1 with two variants: control (current headline) and benefit-led. They add the anti-flicker style to the landing page's head code section, targeting the hero section wrapper with opacity: 0. In the variant script they set headline.innerText = 'Cut your reporting time by 75%' to swap the text when the benefit-led variant is assigned.

The script then sets the wrapper opacity to 1 and wires posthog.capture('hero_cta_clicked') on the CTA. After testing both variants using feature flag overrides in the console and verifying events appear in PostHog's live stream, they publish the site and launch the experiment. After two weeks and 6,000 visitors, the benefit-led headline shows a 23% higher click-through rate with 95% significance, and the marketer ships the winner by updating the Webflow heading directly and removing the experiment code.

Example: Pricing page layout test for a mid-market product

A mid-market project management tool with 8,000 monthly pricing page visitors wants to test whether showing annual pricing as the default (with a toggle to monthly) converts better than showing monthly pricing as the default. The pricing page is in Webflow with three plan cards, each showing both monthly and annual prices. The team has a growth PM and a junior developer.

The developer duplicates the pricing section in the Webflow designer, creating two complete sections: pricing-monthly-default (control) and pricing-annual-default (test). In the test section, they rearrange the cards to show annual prices prominently with monthly prices in smaller text, and pre-select the annual toggle. They set pricing-annual-default to display: none in Webflow's style panel. In PostHog, the PM creates an experiment with a flag key pricing-default-display.

The page script reads posthog.getFeatureFlag('pricing-default-display'). If the value is annual-default, the script sets pricing-monthly-default to display: none and pricing-annual-default to display: block. The conversion event is tracked as a pageview on the /checkout page, configured as the experiment goal directly in PostHog. Both variants are tested across desktop and mobile breakpoints.

After publishing and launching, the team monitors the experiment for three weeks. The annual-default variant shows 18% more clicks to checkout and a 12% increase in average revenue per visitor because more users select annual plans. They ship the annual-default layout, delete the control section from Webflow, and remove the experiment code.

Example: Onboarding welcome page test for a B2C app with Webflow marketing site

A consumer fitness app uses Webflow for its marketing site and a separate React app for the product. New users land on a Webflow welcome page after email verification before being redirected into the app. The team wants to test whether a personalized welcome message ("Welcome, [first name]!") outperforms a generic greeting. They have 2,000 new sign-ups per week.

The team configures PostHog to receive the user's first name as a person property during sign-up (already captured by the React app). On the Webflow welcome page, the PostHog snippet initializes with the user's distinct ID passed via a URL parameter from the app redirect. The script reads posthog.get_property('first_name') and injects it into the heading. If the name is unavailable (edge case), the code falls back to the control text.

The conversion event is tracked when the user clicks the "Start My Plan" CTA, which redirects into the React app. After four weeks, the personalized variant shows a 31% increase in CTA clicks and a 15% increase in users who complete their first workout (tracked as a downstream event in the React app). The team ships personalization as the default and extends the pattern to other Webflow landing pages.

Example: Multi-page funnel test across Webflow and a static checkout page

An e-commerce brand uses Webflow for product pages and a separate static HTML checkout page hosted on Netlify. They want to test whether adding urgency messaging ('Only 3 left in stock') to the product page increases checkout completion. The team has a marketing manager and a freelance developer. Weekly product page traffic is 15,000 visitors.

The freelance developer installs the PostHog snippet on both the Webflow product pages and the Netlify checkout page, using the same PostHog project API key so that user identity persists across domains via the PostHog cookie. In PostHog, they create an experiment with the flag urgency-messaging-pdp. On the Webflow product page, the experiment code checks the flag and, for the urgency variant, unhides a pre-built Webflow element that reads 'Only 3 left in stock' (styled with a red badge). The element is set to display: none by default in the Webflow designer.

The primary conversion event is checkout completion, tracked on the Netlify checkout page when the order confirmation fires. Because the PostHog distinct ID persists across domains, the experiment can attribute checkout conversions back to the variant the user was assigned on the product page. The developer tests cross-domain identity by adding an item to cart in one variant, navigating to checkout, and confirming the PostHog event includes the correct feature flag property. After three weeks, the urgency variant shows a 9% increase in checkout starts but no statistically significant change in checkout completion, suggesting the urgency copy drives more browsing-to-cart behavior but does not affect final purchase intent.

The team decides not to ship and designs a new test targeting checkout abandonment instead.

Best Practices

  • Always use the page-level custom code section for experiment scripts rather than the project-level section. Project-level code runs on every page and will execute unnecessary feature flag evaluations on pages that are not part of the experiment. Page-level code keeps the experiment scoped to exactly the pages involved, reduces JavaScript execution overhead, and makes cleanup straightforward when the experiment ends.

  • Keep the anti-flicker timeout between 1200 and 2000 milliseconds. Below 1200ms, you risk showing the default content to visitors on slow connections before PostHog flags resolve, which contaminates your control group with visitors who briefly saw the wrong variant. Above 2000ms, the blank screen feels like a broken page and increases bounce rate, which hurts both variants equally and wastes traffic. Test the timeout on a throttled connection (use Chrome DevTools Network tab set to "Slow 3G") to find the right balance.

  • Include the variant value as an event property on every conversion event you fire, not just in PostHog's automatic flag tracking. This lets you build custom funnels, filter session recordings by variant, and debug discrepancies between PostHog's experiment view and your own analysis. The property costs nothing to include and saves significant debugging time when results look unexpected.

  • Build both variants in the Webflow designer as distinct sections or elements rather than relying on JavaScript to rewrite content. When the variant logic is limited to toggling visibility of pre-built elements, you eliminate the risk of JavaScript-generated content looking different from the design intent. Designers can review and iterate on both variants in the Webflow canvas, and you avoid complex innerHTML manipulation that can introduce XSS risks or broken markup.

  • Run an A/A test on your first Webflow experiment integration before committing to a real hypothesis. Set up the experiment with identical content in both variants and let it collect data for 48 hours. If the conversion rates diverge significantly, your implementation has a bug, likely in how the anti-flicker code interacts with Webflow's rendering or in how events are tracked. This costs you two days but can save you from running a multi-week experiment on broken infrastructure.

  • Document the Webflow class names and element IDs your experiment code depends on in a comment block at the top of the script. Webflow does not enforce stable class names across redesigns, and a team member editing the page in the designer may inadvertently rename a class. A clear comment listing the dependencies makes this failure mode obvious and recoverable.

  • Use PostHog's $feature_flag_called autocaptured event as a sanity check that flag evaluation is actually happening on the page. Filter your PostHog events by this event name and the specific flag key. If this event is not firing for the experiment's flag, the onFeatureFlags callback is not running, which means none of your variant rendering or event tracking is working.

Common Mistakes

Placing the anti-flicker hide style in the body or in an external stylesheet instead of inline in the head

Correction

When the hide style is in an external CSS file or in a style tag placed in the body, the browser renders the default content for a few frames before the stylesheet loads and applies. The flash may be only 50-100 milliseconds, but it is enough for visitors to read the control headline, which contaminates the test variant's data. You can detect this by recording a slow-motion screen capture of the page load. The fix is to place the opacity style as an inline style tag in the page Head Code section (Webflow labels it "Inside head tag"), ensuring it loads before any content renders.

Using posthog.isFeatureEnabled() instead of posthog.getFeatureFlag() for multivariate experiments

Correction

The isFeatureEnabled method returns a boolean, which works for simple on/off flags but loses the variant information in a multivariate experiment. If your experiment has control, variant-a, and variant-b, calling isFeatureEnabled returns true for all non-control variants, making it impossible to render different experiences for each. Use getFeatureFlag('flag-key') which returns the string name of the assigned variant. Watch for this by checking whether your code branches on true/false rather than on variant name strings.

Not accounting for Webflow's built-in page transitions or interactions that override experiment CSS

Correction

Webflow interactions and page transitions can set opacity, visibility, or display properties that conflict with your experiment code. For example, if a Webflow interaction animates the hero section's opacity from 0 to 1 on page load, it may override your anti-flicker opacity, revealing the control content before your variant code runs. Audit the page's Webflow interactions panel for any load-triggered animations on elements inside your experiment wrapper. Either remove those interactions for the duration of the experiment or set your experiment wrapper to a parent element that is not targeted by any interaction.

Publishing multiple Webflow site versions during an active experiment without checking experiment code

Correction

Every Webflow publish pushes the entire site, including any designer changes team members may have made. If someone renames a class, deletes an element, or changes a section's structure, your experiment script's querySelector calls can silently fail, causing one or both variants to break without any visible error. The result is a period of corrupted data you may not notice for days. Prevent this by communicating active experiment pages to your team and using a pre-publish checklist that includes loading the staged version and verifying both variants still render.

Alternatively, add a simple validation in your script that logs a warning if a target element is not found.

Forgetting to remove experiment code after the experiment concludes

Correction

After shipping the winning variant, teams often leave the PostHog experiment code in the Webflow page's custom code section. This code continues to evaluate feature flags on every page load, adding latency and potentially causing issues if the flag key is reused for a future experiment. More importantly, if the flag is archived in PostHog, the onFeatureFlags callback may not resolve correctly, and the anti-flicker code could leave the page invisible. Build cleanup into your experiment closeout process: remove the page-level custom code, remove any Webflow designer elements that belonged to the losing variant, and verify the page loads cleanly with no console errors.

Testing only on a Webflow staging subdomain that has different caching or CDN behavior than the production domain

Correction

Webflow staging subdomains (*.webflow.io) may have different caching headers, CDN behavior, and third-party script loading compared to your custom production domain. An experiment that works perfectly on staging can flicker on production if a CDN cache serves a stale version of the page without the experiment code, or if the production domain's DNS or proxy adds latency to the PostHog snippet load. Always do a final verification on the production URL after publishing. Use an incognito window to bypass any local caches and watch the page load in DevTools Network tab to confirm the PostHog snippet loads before the DOMContentLoaded event.

Other Skills in This Method

Running A/B Tests in the PostHog Experiments Tab

Step-by-step walkthrough of creating, launching, and monitoring an A/B test using PostHog's Experiments UI, including variant allocation and goal setup.

Setting Up PostHog Feature Flags for Experiment Variants

How to create and configure feature flags in PostHog to assign users to control and test variants in an A/B experiment.

Comparing PostHog Experiments with Eppo, LaunchDarkly, and Other Platforms

How to evaluate PostHog's experimentation capabilities against dedicated tools like Eppo, Statsig, and LaunchDarkly based on analysis methods, integrations, and pricing.

Shipping the Winning Variant and Cleaning Up Feature Flags

How to roll out the winning experiment variant to 100% of users, remove the losing variant's code, and archive feature flags to keep your codebase clean after an experiment concludes.

Designing Experiment Hypotheses and Success Metrics for Onboarding

How to formulate a clear hypothesis, choose primary and secondary conversion metrics, and define what winning looks like before launching an onboarding A/B test.

Segmenting New User Cohorts for Onboarding Experiments

How to target experiments specifically to new users or sign-up cohorts using PostHog's person properties and cohort filters to avoid contaminating results with existing users.

Interpreting Bayesian and Frequentist Results in PostHog

How to read PostHog's experiment results dashboard, understand credible intervals vs p-values, and decide when an experiment has reached statistical significance.

Frequently Asked Questions

How do I prevent flicker when running PostHog Webflow AB tests on pages with heavy images or animations?

The anti-flicker technique hides the experiment wrapper with `opacity: 0` before any content renders, which covers text and layout flicker. For heavy image pages, the images themselves do not cause experiment flicker because they load asynchronously regardless. The risk is that Webflow load animations (set in the Interactions panel) override your opacity hide by animating elements to `opacity: 1` on page load. Audit the page's interactions and disable or retime any load-triggered opacity animations on elements inside your experiment wrapper. If you cannot remove them, set your wrapper to a parent div above the animated elements.

Can I run PostHog experiments on Webflow pages that use Webflow's CMS collections?

Yes, but with a limitation. CMS collection pages use a template, so your experiment code in the page-level custom code applies to every item in the collection. This is useful if you want to test a layout change across all blog posts or product entries. However, if you want to test changes on a specific collection item, you need to add a conditional in your script that checks the current URL path and only runs the experiment logic on the target page. Collection-level experiments work well for broad template changes like CTA placement, sidebar layout, or related content widget positioning.

How long should a PostHog Webflow AB test run on a marketing page?

The minimum duration depends on traffic volume and the minimum detectable effect you care about. For a page with 1,000 weekly visitors and a 5% baseline conversion rate, you need roughly 3-4 weeks to detect a 20% relative improvement with 95% confidence. For smaller effects (10% relative improvement), you need 8-12 weeks or more traffic. PostHog's experiment dashboard shows a recommended sample size when you configure the experiment. Do not stop the experiment early just because one variant looks ahead, as early results are unreliable due to peeking bias. Let it run until PostHog indicates significance or until you reach your pre-committed sample size.

Should I run PostHog Webflow AB tests before or after setting up my conversion events?

Set up and verify your conversion events before launching the experiment. Create the goal event in PostHog, add the tracking code to your page, and confirm events appear in the Live Events stream with correct properties. Then create the experiment and select that event as the goal metric. If you launch the experiment first and add event tracking later, you lose data from the gap period, and your sample sizes will not match across the experimental period. This is covered in more detail in [designing experiment hypotheses and metrics](/skills/designing-onboarding-experiment-hypotheses-and-metrics).

How do I handle returning visitors who see a cached version of my Webflow page without the experiment code?

Webflow's CDN caches pages aggressively. After you publish experiment code, some returning visitors may load a cached version without the experiment script. This means they see the control variant by default but are not tracked in the experiment. To mitigate this, add cache-busting headers if your Webflow plan supports it, or accept that the first few hours after publishing may have a small population of untracked visitors. For most experiments, this is a negligible effect because cached versions expire within Webflow's TTL (usually under 24 hours). If your experiment is particularly sensitive, wait 24 hours after publishing before launching the experiment in PostHog.

Why does my PostHog experiment show uneven traffic split between control and test on my Webflow page?

Uneven splits usually have one of three causes. First, the feature flag targeting rules may include a condition that filters out some visitors before randomization, causing fewer total visitors to enter the experiment. Check the flag's targeting in PostHog. Second, your anti-flicker timeout may be too short, causing slow-loading visitors to see the control variant without triggering the `onFeatureFlags` callback, which means they are not counted in the experiment at all. Increase the timeout to 1500ms and check if the split evens out. Third, if you recently changed the flag configuration, PostHog may have re-randomized assignments, causing a temporary skew. Give it 48 hours to stabilize.

Can I use this same integration approach for Framer, Squarespace, or WordPress instead of Webflow?

Yes, the JavaScript pattern is identical across all no-code builders that support custom code injection. Framer has a custom code section in site settings and per-page settings. Squarespace has code injection under Settings > Advanced. WordPress supports the same approach through a header/footer injection plugin or theme custom code fields. The only differences are where you paste the code and how elements are classed or identified. In WordPress, you may target elements by ID rather than class. In Framer, components have auto-generated class names that are less readable than Webflow's, so consider adding data attributes in Framer's component settings for easier targeting.