BetterLinks & Affiliate Links
Operational notes for BetterLinks + BetterLinks Pro (both 3.0.0) on id86.net, covering click analytics, the cron dependency, the LiteSpeed REST-cache interaction, and the two places affiliate links are stored.
Quick Facts
| Property | Value |
|---|---|
| Plugins | betterlinks + betterlinks-pro (both 3.0.0) |
| Short-link prefix | /link/ (e.g. https://id86.net/link/racknerd) |
| Links table | id86net_betterlinks |
| Clicks table | id86net_betterlinks_clicks |
| Categories table | id86net_betterlinks_terms |
| JSON buffer | wp-content/uploads/betterlinks_uploads/clicks.json |
Click Analytics Flow (two-stage)
BetterLinks does not write clicks straight to the DB. It buffers them:
- Every redirect records a click into
wp-content/uploads/betterlinks_uploads/clicks.json(this is theBETTERLINKS_EXISTS_CLICKS_JSONmode). - The hourly
betterlinks/analyticscron moves the buffered clicks intoid86net_betterlinks_clicksand empties the JSON file back to{}.
Why analytics can appear empty
If the betterlinks/analytics cron never fires, clicks accumulate in clicks.json forever and the Analytics UI / DB stay at 0. On this site the trigger was missing: WP-Cron only fires on page loads, and LiteSpeed page caching intercepted visits before WP ran cron.
The fix that is in place
A real system cron now drives WP-Cron so the hourly sync always happens:
/usr/local/bin/id86-wpcron.sh— runswp cron event run --due-nowas the site user./etc/cron.d/id86-wpcron—*/5 * * * * root /usr/local/bin/id86-wpcron.sh >/dev/null 2>&1wp-config.phpsetsdefine( 'DISABLE_WP_CRON', true );so WordPress does not spawn cron on page loads; the system cron is the only trigger.
Site-scoped (does not affect other sites on the host)
This cron setup is per-site only. The system cron and script hardcode the id86.net path, and DISABLE_WP_CRON lives in this site's own wp-config.php:
id86.net— server cron drives WP-Cron (DISABLE_WP_CRON = true).balancesheet(/home/balancesheet/...) on the same host — untouched, still uses default page-load WP-Cron.
The BetterLinks plugin itself schedules its events with standard WP-Cron (wp_schedule_event(..., 'hourly', 'betterlinks/analytics')). The system cron merely ensures those events are fired reliably rather than depending on page loads (which LiteSpeed page caching skips).
Manual flush if ever needed:
sudo -u Dmg59ZFtKg6bIws1 -- wp --path=/home/Dmg59ZFtKg6bIws1/id86net/public_html \
cron event run betterlinks/analytics
LiteSpeed REST Cache Interaction
BetterLinks' admin UI reads categories/links via authenticated REST endpoints (/wp-json/betterlinks/v1/terms/categories, /terms/tags, /links). LiteSpeed's REST cache (cache-rest, default 7-day TTL) can cache those responses keyed to the logged-in cookie, so after adding a category it saves to the DB but the UI keeps serving the stale cached JSON — the category looks "gone" after refresh.
Both settings must stay off:
wp litespeed-option set cache-rest 0
wp litespeed-option set cache-page_login 0
If LiteSpeed is reactivated (e.g. for production), re-apply these two settings and purge (
wp litespeed-purge all). They are stored inwp_optionsaslitespeed.conf.cache-restandlitespeed.conf.cache-page_login.
Where the Affiliate Links Live
Affiliate links on the Recommendations page (/recommendations/) exist in two places — a DB-only wp search-replace will miss the buttons:
- Theme shortcode (the "Visit X" buttons) — hardcoded in
functions.phpin the child theme:id86_recommendations_shortcode()builds$vpsand$aiarrays with'url'values. Edit →php -l→./deploy.sh→wp flush-opcache flush. - GeneratePress Elements (
gp_elementspost type) — CTA blocks that also render on the page. These live inid86net_posts.post_contentand are edited viawp search-replace.
Current mapping (all point through BetterLinks short links):
| Button | Old affiliate URL | New short link |
|---|---|---|
| RackNerd | https://my.racknerd.com/aff.php?aff=11459 | https://id86.net/link/racknerd |
| GreenCloudVPS | https://greencloudvps.com/billing/aff.php?aff=6685 | https://id86.net/link/greencloudvps |
| Onidel | https://onidel.com/?referral=1567346 | https://id86.net/link/onidel |
| OpenCode Go | https://opencode.ai/ | https://id86.net/link/opencode |
OPcache Note
The wp flush-opcache flush WP-CLI command flushes the CLI SAPI (PHP 8.0), not the web worker (lsphp83/84). The web opcache is configured with validate_timestamps=1 and revalidate_freq=60, so a theme deploy is picked up within ~60s automatically. If a change must appear instantly, either wait ~60s or restart the relevant lsphp worker.
Update Safety
None of the above requires modifying BetterLinks plugin code. Everything lives in:
wp-config.php(DISABLE_WP_CRON)- LiteSpeed plugin settings (
wp_options) - The child theme
functions.php - System cron files (
/etc/cron.d/,/usr/local/bin/)
Plugin updates therefore cannot break these changes.