Published May 21, 2026
This tutorial explains how to integrate LaunchDarkly with a self-hosted WordPress site for feature flagging and experimentation. It covers the available SDK approaches, how to handle WordPress-specific constraints like caching, and how to structure your implementation depending on whether your goal is controlled feature rollouts or A/B testing.
WordPress powers a large share of the web, and many organizations use it alongside modern JavaScript front ends and microservice architectures. LaunchDarkly supports this kind of mixed environment through a combination of the PHP server-side SDK and the JavaScript client-side SDK.
This tutorial applies to self-hosted WordPress sites on wordpress.org. Sites hosted on wordpress.com do not provide PHP execution access and cannot run the LaunchDarkly PHP SDK. For those environments, use the JavaScript SDK with client-side flag evaluation only.
To complete this tutorial, you should have:
Before you read this tutorial, you should understand the following:
kind (usually user) and a key that uniquely identifies the entity being evaluated.There are two main approaches to integrating LaunchDarkly with WordPress. Your choice depends on your WordPress setup and requirements.
Most production experimentation use cases on self-hosted WordPress will benefit from the PHP SDK approach. The sections below cover both approaches.
This approach evaluates flags server-side in PHP and injects the results into the page before it reaches the browser. The JavaScript SDK initializes instantly from those pre-evaluated values.
From your WordPress root or theme directory, install the SDK using Composer:
Then include the autoloader in your theme’s functions.php:
The LaunchDarkly PHP SDK version 6.x requires PHP 8.1 or higher. Starting with version 6.6, it also requires the apcu PHP extension to be installed and enabled.
Add the following to your theme’s functions.php. This function evaluates all client-side flags for the current user and outputs them as an inline script that the JavaScript SDK can read on initialization.
By default, the PHP SDK caches flag data in memory per process. This is appropriate for low-to-medium traffic environments. For higher-traffic sites, you can configure the SDK’s HTTP cache to use Memcached or Redis using the cache option, or use the Relay Proxy in daemon mode which is LaunchDarkly’s recommended approach for high-throughput PHP environments.
In your theme or page template, initialize the JavaScript SDK using the injected bootstrap values. The SDK will be immediately ready with no network fetch required.
Register the SDK script alongside your other theme assets. We recommend self-hosting the SDK file rather than loading it from a third-party CDN like unpkg or jsDelivr, which we do not support for production use. To learn more, read the JavaScript SDK reference.
Full-page caching (WP Rocket, W3 Total Cache, Nginx FastCGI, Cloudflare, and similar caching layers) stores a rendered HTML snapshot and serves it to all subsequent visitors. This means PHP does not re-execute per user, and the same evaluated flag values are served to everyone.
This is not a LaunchDarkly-specific limitation. It affects any server-side A/B testing tool running on a cached WordPress page.
There are two approaches to resolve this.
This pattern keeps full-page caching enabled for the majority of traffic while ensuring each user receives a correctly bucketed, consistent variant.
How it works:
If you’re using PHP, evaluate once and set a cookie:
Set the variant cookie expiration to match or exceed your typical experiment duration. If a returning visitor’s variant cookie has expired, they’ll be re-bucketed on their next visit, which can cause variant jumping in long-running experiments.
If you’re using JavaScript, read the variant on cached page loads:
The PHP variation() call that sets the cookie records the experiment exposure server-side, so subsequent cached page loads do not need to fire another exposure event from JavaScript. Use the bootstrapped variant to gate your UI, and use ldClient.track() to record conversion events on the same context key. Avoid passing the full allFlagsState() payload through the cookie, since that bootstrap form is intended to be regenerated per-request by the server and grows with your client-side flag count. To learn more, read Bootstrapping.
Configure your caching layer to bypass cache when the variant cookie is absent, for example, new visitors who need a fresh PHP evaluation:
It is also possible to disable caching entirely on pages where an experiment is running. This is the simplest configuration change but means those pages lose the performance benefit of full-page caching.
We generally do not recommend this approach for SEO-critical or high-traffic landing pages where cache performance is a requirement. It may be appropriate for lower-traffic pages where cache performance is less important.
If you are unable to modify PHP or are running on a platform where PHP execution is restricted, you can use the JavaScript SDK alone.
Self-host the SDK file alongside your other JavaScript resources and load it from your theme’s <head> using wp_enqueue_script().
When the SDK loads asynchronously, the page renders before flag values are available. Users may briefly see the control variant before the treatment is applied. This is called “flicker.”
To prevent flicker, hide the element under test until the SDK is ready, then reveal it:
Loading the SDK with async or defer improves page load metrics but makes flicker worse, because the page renders before the script executes. If you use async/defer, the CSS hide pattern above becomes essential. The PHP bootstrap approach in Option 1 eliminates this tradeoff entirely.
By default, the JavaScript SDK fetches flags from LaunchDarkly on every page load, so the ~100–200ms cold start applies to every initialization. To cache flag values across visits, pass bootstrap: 'localStorage' to LDClient.initialize(). With this enabled, after the first visit the SDK reads cached values from localStorage and emits the ready event immediately, while still fetching the latest values in the background. Note that this can introduce stale-value flicker if flags change between visits, and that first-time visitors still see the full cold start. The PHP bootstrap approach in Option 1 avoids both tradeoffs.
Feature flags let you control which users see which experiences without code deployments. Common use cases in WordPress include:
In your WordPress template, add the following:
In the LaunchDarkly UI, set the flag to a 20% percentage rollout to gradually expose the new hero to traffic. Increase the percentage as confidence grows, or roll back instantly by turning the flag off.
Experimentation builds on feature flags to run controlled A/B tests and measure the effect of changes on defined metrics. The typical WordPress experimentation flow involves the landing page (WordPress), downstream conversion pages (often React or other front-end apps), and a metric like signup or purchase completion.
To set up an experiment:
control and treatment. Enable client-side SDK access on the flag.signup-completed. Set the metric type to Occurrence (did this event happen for this user at all?).track() call from wherever that event occurs, whether that’s the WordPress page itself or a downstream React application:LaunchDarkly connects the track() event to the experiment exposure using the same context key. As long as the same userId or visitorId is used consistently across your WordPress LP and downstream apps, attribution will be correct.
If your WordPress LP is the entry point but conversion happens in a React app on the same domain, you can persist the variant assignment in a cookie and read it in the downstream app without re-initializing LaunchDarkly:
This approach requires the WordPress LP and the React app to share the same root domain. If they are on separate domains, initialize the LaunchDarkly SDK in each app using the same context key instead.
When a user arrives anonymously and later signs up or logs in, you can link their pre-login experiment exposure to their authenticated identity using a multi-context identify call. This ensures experiment attribution is preserved across the anonymous and authenticated states.
At the moment of login or signup:
Marking the visitor sub-context as anonymous: true is recommended for most A/B testing scenarios because it reduces your monthly active user (MAU) consumption and excludes pre-login traffic from the contexts list. If you instead want to individually target specific anonymous visitors, audit which variations each visitor saw, or preserve pre-login attributes as a durable record on the contexts list, omit anonymous: true so the visitor is tracked. To learn more, read Anonymous contexts.
Note also that visitor is a custom context kind defined by your application. If you use this kind, use the same kind name consistently across your application and in any experiment’s randomization unit configuration. To learn more, read Contexts.
For WordPress sites with significant traffic, configure the PHP SDK to use the LaunchDarkly Relay Proxy in daemon mode. The Relay Proxy maintains a persistent connection to LaunchDarkly and stores flag data in Redis or DynamoDB. This means:
This requires the launchdarkly/server-sdk-redis-predis (or launchdarkly/server-sdk-redis-phpredis) Composer package, and the Relay Proxy must be configured to write to the same Redis instance. To learn more, read Using daemon mode and Storing data.
To learn more, read The Relay Proxy.
In this tutorial, you learned how to:
For more information, read: