Skip to main content

Data Sharing

Burst Statistics v3.3.0 includes an anonymous usage data collection system (telemetry) that sends aggregated, non-personal statistics to the Burst Statistics team once per month. This data helps improve the plugin.

No personally identifiable information is collected. All data is anonymised at the point of collection using a one-way site hash.


Overview

The data sharing system is made up of two main components:

ClassResponsibility
Burst\Admin\Data_Sharing\Data_SharingSchedules and triggers the monthly telemetry send
Burst\Admin\Data_Sharing\Data_AggregationCollects, aggregates, and dispatches the payload

Data is collected by individual data collectors (one per category) and combined into a single JSON payload sent via HTTP POST to:

https://api.burst-statistics.com/v2/telemetry
caution

Telemetry is never sent from staging environments. See Staging detection for the full list of detected patterns.


Scheduling

The send is triggered by the burst_monthly WordPress cron action. When that fires, a single-event cron job (burst_telemetry_send) is scheduled with a random offset between 24 and 720 hours. This spreads load across the month rather than all sites sending simultaneously.

The random offset is stored persistently in the burst_telemetry_offset option so the same offset is reused if WordPress cron runs multiple times before the event fires.

Relevant WordPress options:

OptionDescription
burst_telemetry_offsetRandom hour offset (24–720) used to stagger the send time
burst_last_telemetry_sendUnix timestamp of the most recent successful send

Data collected

Each category is collected by a dedicated Data_Collector subclass. The aggregated payload always includes:

FieldTypeDescription
site_hashstringSHA-256 hash of site_url + AUTH_KEY. Identifies the site without transmitting the URL.
is_testbooltrue only during test sends. Test payloads are validated but not stored by the API.
settingsobjectActive plugin settings
goalsobjectConfigured conversion goals
environmentobjectWordPress version, PHP version, and similar environment metadata
email_reportsobjectEmail report configuration (not personal email addresses)
metricsobjectAggregated pageview and event counts for the reporting period

Anonymisation

The site identifier sent in every payload is a one-way SHA-256 hash:

hash( 'sha256', get_site_url() . AUTH_KEY );

The raw site URL is never transmitted. Two sites with the same URL but different AUTH_KEY values produce different hashes.


Kill switch

Before each send, Burst fetches a plain-text control file from:

https://burst.ams3.cdn.digitaloceanspaces.com/feedback/switch.txt

The response body controls whether the send proceeds:

Response bodyBehaviour
enabledSend proceeds normally
disabledSend is skipped for all sites
0100 (integer)Send proceeds for that percentage of sites (random per-site roll)
Any other value / unreachableSend proceeds (fail-open)

If the kill switch disables a send, burst_last_telemetry_send is still updated so the site does not retry on the next cron cycle.


Staging detection

No data is sent when the site is identified as a non-production environment. The check uses wp_get_environment_type() first, then inspects the site URL for the following patterns:

Pattern typeExamples
Environment type not productionstaging, development, local (WP core values)
Localhostlocalhost, localhost/…
Local TLD*.local
Staging subdomain prefixstaging.*, stg.*, test.*, beta.*, acceptance.*
Staging subdomain infix*.dev.*, *.test.*, *.stg.*
Managed staging hosts*.instawp.co

Caching

Aggregated data is cached in the burst_aggregated_data transient for one week. This reduces database load on repeated API calls. The cache is bypassed when wp_get_environment_type() is not production.

To clear the cache programmatically:

$aggregation = new \Burst\Admin\Data_Sharing\Data_Aggregation(
strtotime( '-1 month' ),
time()
);
$aggregation->clear_cache();

API request format

Payloads are sent as JSON POST requests with these headers:

HeaderValue
Content-Typeapplication/json
Acceptapplication/json
HTTP_X_BURST_SIGNATUREValue of the BURST_PUBLIC_KEY constant

WordPress cron hooks

burst_monthly

Fires once per month via Burst's internal cron management. The data sharing system uses this action to schedule the deferred telemetry send via Data_Sharing::schedule_telemetry().

This action is not exclusive to data sharing — other subsystems also hook into it.

burst_telemetry_send

Single-event cron hook that performs the actual data collection and API send. Scheduled by Data_Sharing::schedule_telemetry() with a random offset after burst_monthly fires.

Parameters: none.

Example — observing the send:

add_action( 'burst_telemetry_send', function() {
// Executes immediately before Burst sends telemetry data.
}, 1 );
caution

Removing burst_telemetry_send prevents the send only for the currently scheduled event. The next burst_monthly cycle will reschedule it.


Disabling data sharing

Data sharing is suppressed automatically on staging and local environments (see Staging detection).

To disable it unconditionally on a production site, prevent the cron hook from running before Burst's own callback:

// In a must-use plugin or your theme's functions.php.
add_action( 'burst_telemetry_send', function() {
remove_action(
'burst_telemetry_send',
[ burst()->data_sharing, 'send_monthly_telemetry' ]
);
}, 0 );

To prevent the event from ever being scheduled, intercept burst_monthly early:

add_action( 'burst_monthly', function() {
remove_action(
'burst_monthly',
[ burst()->data_sharing, 'schedule_telemetry' ]
);
}, 1 );

Test sends

Data_Sharing::send_test_telemetry() dispatches a payload with is_test: true. The API validates the payload structure but does not persist the data. An optional custom endpoint can be passed for integration testing.

$data_sharing = new \Burst\Admin\Data_Sharing\Data_Sharing();
$result = $data_sharing->send_test_telemetry();

if ( $result['success'] ) {
echo 'Accepted. HTTP ' . $result['status_code'];
} else {
echo 'Failed: ' . $result['message'];
}

Return value:

KeyTypeDescription
successbooltrue if the API returned a 2xx status code
status_codeintHTTP response code
messagestringHuman-readable status from the API response body
dataarray|nullFull parsed JSON response body
endpointstringURL the request was sent to

When a visitor arrives via a share link, Burst assigns the burst_viewer role and grants the view_burst_statistics capability. This allows the visitor to access general statistics pages that were included in the shared link's shared_tabs array.

Breaking change

Changed in v3.3.0: view_sales_burst_statistics has been removed from the allowed_caps list checked when filtering capabilities for shared-link visitors. The burst_viewer role is also no longer granted the view_sales capability automatically. Previously, any shared-link visitor implicitly received sales/ecommerce access alongside their view access.

Allowed capabilities for shared-link visitors (v3.3.0+):

$allowed_caps = [
'view_burst_statistics',
'burst_viewer',
];
Pro

Ecommerce tab sharing requires Burst Pro.

Access to the ecommerce (Sales) tab on a shared link is now controlled exclusively by the ecommerce_tab_is_shared() method on Burst\Admin\Share\Share. It inspects the shared_tabs array stored on the token and returns true only when 'sales' is present.

// Resolved automatically via burst_loader()->admin->share.
$share = burst_loader()->admin->share;
$can_view_sales = $share->ecommerce_tab_is_shared();

Internally, user_can_view_sales() (from the Admin_Helper trait) delegates to this method whenever is_shared_link_request() returns true:

// From trait-admin-helper.php — simplified illustration.
if ( $this->is_shared_link_request() ) {
return burst_loader()->admin->share->ecommerce_tab_is_shared();
}

Added in v3.3.0. A protected helper available to any class using the Admin_Helper trait. Returns true when the current request carries either of the two share-token identifiers.

protected function is_shared_link_request(): bool {
return isset( $_SERVER['HTTP_X_BURST_SHARE_TOKEN'] )
|| isset( $_GET['burst_share_token'] );
}

This helper is used as a guard inside user_can_view_sales() and can be called from any class that uses Admin_Helper to branch logic for anonymous shared-link visitors versus authenticated users.