Guide
Running the WooCommerce plugin
Install the plugin, connect it with your setup code, watch it in shadow mode, switch enforcement on, keep an eye on it, and remove it — in that order.
Last updated
The plugin runs inside your own WordPress. It verifies each shopper’s signed admission pass locally, enforces one order per admission at checkout, and — until you say otherwise — enforces nothing at all. This guide is the operator’s path through it, in the order you will do it. What the plugin can and cannot enforce compared with the edge connector is spelled out where it matters below; running both is covered in Running both adapters.
Requirements: WordPress 6.0+, WooCommerce 7.0+, PHP 8.1+. The PHP floor is hard — the signature check depends on a function that older versions do not have.
1. Install and connect
- Get the plugin zip from the console’s Install the adapter page.
- Plugins → Add New → Upload Plugin, then activate. The plugin activates in shadow mode (log-only) by default, so activating it on a live store blocks nobody.
- Open Settings → Dropify and paste the setup code from the same console page. One paste fills the Store ID, the adapter key and the API URL. The individual fields are under Advanced configuration, and any of them can instead be pinned as a
wp-config.phpconstant — a constant always wins and greys out its field. The plugin’s own settings screen lists the constants. - Press Test connection now. Expect Connection OK — policy & keys verified.
What “Test connection now” actually tests
It is a forced, cache-bypassing round trip that names the stage that failed:
| Stage | What failed | First things to check |
|---|---|---|
pubkey | Our public key could not be fetched | API URL typo; outbound HTTP blocked from your server (see below); DNS or TLS from the server |
policy-fetch | Your store’s policy could not be fetched | Store ID typo (an unknown store is a 404); an outage on our side |
policy-verify | The policy’s signature did not verify | The wrong API URL for this store; tampering in between |
policy-rollback | A validly signed but older policy arrived | Possible replay or downgrade; the plugin keeps its last-known-good copy — investigate before a drop |
epoch-keys | The verification keys were refused or empty | A rotated or wrong adapter key (401) — the most common cause; a billing lapse (402) |
A successful probe also counts as a heartbeat for the plugin, so the console’s Run check on the Install page flips to Connected immediately after a good one.
If the banner says WordPress itself is refusing the request: your site defines WP_HTTP_BLOCK_EXTERNAL and our host is not in WP_ACCESSIBLE_HOSTS. Add it there — the error message names the exact host.
2. Shadow, verify, enforce
The recommended rollout: leave the plugin in shadow for a drop or two, read the log, then switch to enforce.
-
Shadow is genuinely non-acting. Gate decisions are logged, nothing is blocked, and the single-page-storefront helper script is deliberately not sent to browsers while shadowing.
-
Reading the log needs
WP_DEBUG. Gate decisions are logged through WordPress’s debug log; withWP_DEBUGandWP_DEBUG_LOGon,wp-content/debug.logshows lines like:[dropify] SHADOW would queue: path drop=default (tenant=…) [dropify] SHADOW would queue: checkout drop=default (tenant=…)What to look for: the gated paths you expected, no entries for paths that should be let through, and no flood of no signed policy — brain unreachable lines (that one means the store would enforce nothing). One class of problem is logged without
WP_DEBUG: a policy version this build of the plugin refuses. That line means zero gating until the plugin is updated, and it is exactly what the version interlock exists to protect you from. -
Switch to enforce with the one-click Mode card at the top of Settings → Dropify. If the mode is pinned by
DROPIFY_SHADOWinwp-config.php, the button says so and refuses — remove the constant to switch from the UI.
After switching, verify from a clean browser (or curl with no cookies): with the queue enabled, a storefront request should redirect (302) to the waiting room, wait its turn, and hand you back with a pass. Add-to-cart and checkout without a pass are refused with a WooCommerce error notice rather than a redirect — that is the commerce surface, which no allowlist entry or setting can exempt.
3. Ongoing health: Site Health and the two dashboards
- Tools → Site Health → Status carries a Dropify connection test. It renders the same single verdict as the settings banner, so the two can never disagree. The verdict distinguishes: WooCommerce inactive / not configured / cannot reach Dropify (with the persisted reason) / configured but never verified / connected in shadow / connected but queue off / connected and enforcing.
- The console’s Run check (Install the adapter → Verify the connection) asks whether we have seen this store’s key pulls. Not connected there with a green banner in WP Admin almost always means a rotated adapter key — re-paste a fresh setup code. The plugin heartbeats on any PHP bootstrap (admin, front, cron) about every ten minutes, independent of whether anything is being gated. A stale badge means no pull in thirty minutes — a liveness signal, not a loss of whole-shop gating. Test connection now refreshes it immediately.
- Diagnostics persist without
WP_DEBUG: the settings screen’s status grid shows the last policy and key pull times and the last specific error.
4. Behind a proxy
Forwarded-IP headers are trusted only when the actual TCP peer is in the trusted-proxy list. Cloudflare’s published ranges are the default; anything you enter replaces that default; none trusts only the direct connection; the hop count reads X-Forwarded-For from the right. Get it wrong in the safe direction and passes stop being tied to individual shoppers — the plugin raises a persistent admin notice when it detects that state, because nothing else about it looks broken. Configure it under Settings → Dropify → Advanced, or with the DROPIFY_TRUSTED_PROXY_CIDRS and DROPIFY_TRUSTED_PROXY_HOPS constants.
One limit to know: trusting a proxy is only as good as the proxy. An attacker who fronts your origin with their own Cloudflare account connects from a legitimate Cloudflare range. The defence for that is Authenticated Origin Pulls or an origin firewall, not a CIDR list.
5. What plugin-only does not cover
These are structural limits of enforcing at the origin, and they are the honest reason to add the edge connector rather than a sales one:
- REST catalogue reads are not gated. The WordPress REST API (
/wp-json) never runs the hook the plugin gates on, so a queued visitor can still read product data. An accepted trade — the fix would be an availability risk — and an operational reason to add the edge if you sell headless or care about scraping during drops. - A cache that answers without invoking PHP defeats the plugin. LiteSpeed at server level, nginx
fastcgi_cacheorproxy_cache, Varnish, or CDN full-page caching: the plugin’s no-cache signals only work when PHP runs. Do not run plugin-only in that topology. - The origin absorbs the whole crowd. Every queued visitor’s poll is a WordPress bootstrap, so the store still has to survive the crowd even though the allocation is fair. A network flip mid-session rebinds a shopper’s pass within the configured budget and then re-queues them; and the single-page-storefront helper’s reactive mode needs the edge’s signal to work.
If any of those bite, add the edge connector on top — Running both adapters.
6. Uninstall
- Deactivate stops all gating and lifecycle hooks immediately; configuration and cached artifacts stay for a re-activation.
- Delete (Plugins → Delete) removes every option and transient the plugin wrote — settings, diagnostics, cached policy and keys, spent and pending visitor markers — and flushes the persistent object cache. Order meta stamped on past orders (
_dropify_queue_*,_dropify_pass_*) is deliberately kept: it is your commerce record.
The store fails open at every step. The plugin is incapable of taking the store down by being removed, misconfigured, or cut off from us.
7. LiteSpeed Cache settings
The plugin sends LiteSpeed its own no-cache signals, but a few settings on the LiteSpeed side make the two cooperate properly on a LiteSpeed-backed server:
-
Do Not Cache Cookies — under LiteSpeed Cache → Cache → Excludes → Do Not Cache Cookies, add:
dropify_pass dropify_bind dropify_hint dropify_bounceThis stops LiteSpeed serving a cached page meant for another visitor to a shopper holding an active pass.
-
Exclude the commerce URIs — under LiteSpeed Cache → Cache → Excludes → Do Not Cache URIs, make sure your store’s cart, checkout and shop paths are present. The plugin’s one-click auto-configure derives them from your WooCommerce page settings (
/winkel*on a Dutch store,/warenkorb*on a German one):/cart* /checkout* /shop* -
If you also run the edge connector, keep LiteSpeed’s combined assets out of the Worker: in Cloudflare → Workers Routes, add a route for
shop.example.com/wp-content/litespeed/*pointing to Worker: None, so the minified CSS and JS are served straight from the CDN. Read the warning about route wildcards in the edge connector guide first. -
Cookie Vary for pass holders (optional, high-traffic stores) — under LiteSpeed Cache → Cache → Vary → Cookie Vary, add
dropify_passso LiteSpeed keeps separate cached page buckets for pass holders and everyone else.