- 0.3.1: Refused beacons are now written to the debug log, so a missing or expired nonce shows up there like other nonce failures. Until now a refusal was a silent 403: LH WP Die Logger only reports nonce failures when wp_die() runs, which a REST refusal never does, and WordPress does not even announce a missing nonce. Each refusal is logged as a Warning tagged [lh_beacon] in the standard LH format: event beacon_refused, a reason (too_large, origin, rate_limited, invalid_shape, nonce_missing or nonce_invalid), the site, the Origin and Referer headers and the body size. Nonce refusals add the user ID from the login cookie and the beacon keys, and rate-limit refusals add the IP address. Payloads and the nonce itself are never logged. Logging only happens when WP_DEBUG is on, and can be switched off with the lh_beacon_return_plugin_debugging_status filter.
- 0.3.0: Every beacon must now carry a valid nonce, for logged-out visitors as well as logged-in ones. LH Beacon prints a nonce into the page with its settings and sends it in the request body. The collect route verifies it against the visitor the login cookie identifies (user 0 when logged out) and refuses the request with a 403 (lh_beacon_invalid_nonce) when it is missing or invalid; nothing is dispatched. The nonce goes in the body rather than the X-WP-Nonce header so that a stale one is refused by LH Beacon with its own error, not by the REST API's cookie check. This is defence in depth on top of the existing same-origin, size and rate checks: a beacon now has to come from a page this site served to that visitor within the nonce's lifetime. That lifetime is 12 to 24 hours, so pages must not be served from cache for longer than 12 hours: on LocalHero the LiteSpeed public cache TTL was cut from 7 days to 12 hours alongside this release. A beacon from a page left open past its nonce's lifetime is refused, so a little long-tail data is lost. The lh_beacon_require_nonce filter can switch the check off in an emergency. The lh_beacon_get_user_id filter now runs after the nonce has been checked against the real cookie user, so anonymising the ID no longer affects verification.
- 0.2.0: LH Beacon now tells consumers who sent a beacon. When the visitor is logged in, their user ID is passed as a new last argument to both the lh_beacon_received and lh_beacon_received_{key} actions, so existing listeners keep working unchanged; it is 0 for logged-out visitors. During dispatch it is also available from LH_Beacon_plugin::return_current_user_id(). The visitor is identified from their logged_in cookie rather than a REST nonce, because a page served from cache cannot carry a valid nonce and a stale one would make the REST API refuse the whole request. The cookie is only read for requests that have already passed the same-origin check. The ID is an identity only: LH Beacon does not switch the current user, so consumers do not gain that user's capabilities. A new lh_beacon_get_user_id filter can change or anonymise the ID (return 0).
- 0.1.0: First release. Plugins queue payloads in the browser with lhBeacon.set( key, payload ), and LH Beacon sends everything queued in one sendBeacon request (fetch keepalive fallback) when the page is hidden or closed, once per hide. On the server the lh-beacon/v1/collect route checks only the request envelope (same origin, at most 8192 bytes, at most 300 requests per IP per minute, all filterable) and passes each payload unread to the lh_beacon_received and lh_beacon_received_{key} actions, so every consumer validates and stores its own data. The script is registered but never enqueued on its own: it loads only where a plugin's script depends on lh-beacon.