Documentation · Set up
Server setup
Two settings on your server decide whether a visitor's request really costs the plugin about 0.02 ms of PHP with no database query and no network call. The plugin checks both and shows a notice in wp-admin until they are in place. Setting them first means never seeing the notice. Both involve your server, so you may want your developer or host to do them.
1. A private data directory
Every event the plugin records (an order, a payment, a form submission, a sampled request) is appended to a local file and uploaded later by a scheduled task. That file must be private, so it cannot be fetched over the web, and writable by PHP. Name a directory outside your web root in wp-config.php:
// wp-config.php: a directory OUTSIDE your web root that the web server user can write to.
// cPanel-style, next to public_html:
define( 'OPERANSE_DATA_DIR', '/home/youruser/operanse-data' );
// Cloudways:
// define( 'OPERANSE_DATA_DIR', '/home/master/applications/<app>/private_html/operanse-data' );
// A VPS with the site in /var/www/html:
// define( 'OPERANSE_DATA_DIR', '/var/www/operanse-data' );The plugin creates the directory with permissions that let only the web server user read it, refuses a path that resolves to inside the document root, and re-checks that it can write there once a day. The constant takes effect on the next page load.
Where the buffer goes without it
| Tier | Where | How privacy is established |
|---|---|---|
| 1 | OPERANSE_DATA_DIR | By construction: the path is outside the document root, so no address maps to it. |
| 2 | wp-content/uploads/operanse-agent/spool | This directory is inside the web root, so once a day the plugin writes a random token file and fetches its own address. The directory is used only if the server refuses the request. |
| 3 | A size-limited table in your database | The fallback when neither of the above can be proven. |
On the database tier the plugin does what it otherwise never does: on the request that produced an order, payment, webhook or form event it runs a SELECT and an INSERT on your database, about 1.8 ms. It also switches request sampling off rather than pay that for page views, so there is no request-timing data. The table is bounded at 20,000 rows and the site keeps working. It is a cost, not a fault, and the one line above removes it.
Managed hosts. On Cloudways the application directory itself is not writable; use the app's private_html/, which exists for this and is outside public_html. On cPanel, a directory next to public_html works.
Several web servers. If more than one web node serves the site, give each node its own local directory (the same path on each is fine), not a shared network mount. The buffer is appended under a file lock, which is slow or unreliable on NFS, and each node's buffer is uploaded by whichever scheduled run lands on it.
2. A system cron
All of the plugin's work (collecting, uploading, checking for read jobs, the inventory) runs from WP-Cron. WordPress's built-in cron trigger only fires when the site receives a visit, runs the work inside that visitor's request, and depends on a loopback request that fails on many hosts. Disable the built-in trigger and run a real cron every minute:
// wp-config.php
define( 'DISABLE_WP_CRON', true );* * * * * cd /path/to/wordpress && wp cron event run --due-now --quietIf WP-CLI is not available, fetch the cron endpoint instead:
* * * * * curl -s https://example.com/wp-cron.php?doing_wp_cron > /dev/nullThis also makes your store's own background work (renewals, scheduled actions, emails) run on time on a quiet site.
Verify
wp cron test
wp operanse statuswp operanse status prints the buffer tier and location, the last upload, the last heartbeat and the result of the plugin's own cron check. Settings → Operanse shows the same.
What the notices mean
| Notice | When it shows | It goes away when |
|---|---|---|
| Operanse is buffering events in your database | The buffer is on the database tier | A private directory is in use |
| WP-Cron is not running reliably on this site | The site is paired and the cron check failed or a collection ran late | The next collection runs on time |
| Operanse runs on WordPress's built-in cron trigger | DISABLE_WP_CRON is not set | It is set to true |
Notices are shown to administrators on the Dashboard, the Plugins screen and Settings → Operanse, and nowhere else. A dismissed notice stays dismissed for the same condition and returns if the reason changes. The same state reaches the dashboard through the heartbeat, so the site page says the same thing.