Tasks system
The tasks system in Burst Statistics surfaces actionable notices in the admin dashboard. Tasks notify site administrators about warnings, errors, plugin milestones, promotional offers, and configuration recommendations. Developers can register custom tasks using the burst_tasks filter.
Overview
Tasks are defined as PHP arrays in includes/Admin/App/config/tasks.php and merged at runtime via the burst_tasks filter. Each task has an ID, a message, an icon type, and an optional condition that controls when it appears.
Active task IDs are stored in the WordPress option burst_tasks. The admin UI reads this list and merges it with the full task definitions to determine what to display.
Task lifecycle
- Registration — Tasks are defined in the config file or added by the
burst_tasksfilter. - Activation — Tasks with
condition.type = activationare written toburst_taskson plugin activation. - Validation — A scheduled event (
burst_validate_tasks) runs every time task validation is triggered. It evaluates allserversideconditions and adds or removes task IDs fromburst_tasksaccordingly. - Display —
get_tasks()readsburst_tasks, merges active IDs with task definitions, filters out dismissed tasks, and sorts results (warnings first, then open, then other). - Dismissal — When a user dismisses a task, it is removed from
burst_tasks. If the task hasdismiss_permanently = true, its ID is also stored inburst_tasks_permanently_dismissedand will never be re-added.
Task definition fields
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier for the task. Sanitized with sanitize_title() when stored. |
msg | string | No | Translated message shown to the user. Supports HTML. |
icon | string | No | Icon type that controls the label and sort order. See Icon types. Defaults to 'open'. |
url | string | No | Link URL. Relative paths are prefixed with the Burst website URL and UTM parameters. Paths starting with # are treated as internal links. Full https:// URLs are passed through unchanged. |
condition | array | No | Controls when the task is active. See Condition types. |
dismissible | bool | No | Whether the user can dismiss the task. |
dismiss_permanently | bool | No | If true, dismissing the task stores it in burst_tasks_permanently_dismissed and it will never be shown again, even if the condition becomes true again. |
plusone | bool | No | If true, the task increments the admin-bar badge counter. |
fix | string | No | Identifier for a fix action available in the UI. Can be a WordPress option name (to toggle an option) or a Burst action name. |
Icon types
The icon field determines the badge label shown alongside the task and affects sort order.
| Icon value | Label | Sort priority |
|---|---|---|
warning | Warning | 1st (top) |
error | Error | 1st (top) |
open | Open | 2nd |
completed | Completed | 3rd |
new | New! | 3rd |
sale | Sale | 3rd |
offer | Offer | 3rd |
milestone | Milestone | 3rd |
insight | Update | 3rd |
pro | Pro | 3rd |
Tasks with icon = 'success' are given a status of 'completed'; all others receive 'open'.
If the site administrator has enabled the Dismiss non-error notices setting (dismiss_non_error_notices), only tasks with icon = 'error' will be displayed, regardless of their condition.
Condition types
The condition field is an array with a required type key.
activation
The task is added to burst_tasks once when the plugin activates. It has no server-side re-evaluation; it persists until dismissed.
'condition' => [
'type' => 'activation',
],
serverside
The task is evaluated on every task validation run. The condition resolves to a boolean via a function or constant key.
Show code
'condition' => [
'type' => 'serverside',
'function' => 'MyPlugin\MyClass::is_active()',
],
If the condition is true, the task is added. If false, the task is dismissed (unless it has dismiss_permanently).
Supported function formats:
| Format | Example | Description |
|---|---|---|
| WordPress option check | 'wp_option_burst_missing_tables' | Returns true if the option exists (is not false). Strip the wp_option_ prefix to get the option name. |
| Static method call | 'Burst\Admin\Admin::is_bf()' | Calls ClassName::methodName(). |
| Instantiated method call | '(new Burst\Admin\Milestones())->pageviews_milestone_reached()' | Instantiates the class, then calls the method. |
| Chained call | 'base()->class->method' | Calls a method on a chained object. |
| Inversion | Prefix any format with ! | Negates the result. |
Using a constant:
Show code
'condition' => [
'type' => 'serverside',
'constant' => 'MY_PLUGIN_CONSTANT',
],
Returns true if the constant is defined. Prefix with ! to invert.
clientside
The task is always included in the task list sent to the browser. The front-end JavaScript evaluates whether to display it. Client-side tasks bypass the burst_tasks option entirely — they are never filtered by has_task().
'condition' => [
'type' => 'clientside',
],
Built-in tasks
The following tasks ship with Burst Statistics.
| ID | Icon | Condition type | Dismissible | Permanent dismiss | plusone |
|---|---|---|---|---|---|
bf_notice | sale | serverside | Yes | Yes | Yes |
cm_notice | sale | serverside | Yes | Yes | Yes |
leave-feedback | completed | activation | Yes | No | — |
join-discord | completed | activation | Yes | No | — |
ecommerce_integration | new | — | Yes | No | No |
search_console_integration | new | — | Yes | No | Yes |
cron | warning | — | No | No | — |
malicious_data_removal | warning | serverside (wp_option_burst_cleanup_uid_visits) | Yes | No | — |
php_error_detected | warning | serverside (wp_option_burst_php_error_detected) | Yes | No | — |
missing_tables | warning | serverside (wp_option_burst_missing_tables) | Yes | No | — |
pageviews_milestone | milestone | serverside (Burst\Admin\Milestones::pageviews_milestone_reached()) | Yes | No | No |
live_visitors | insight | clientside | No | No | No |
multi_domain_setup_detected | warning | serverside (wp_option_burst_is_multi_domain) | Yes | Yes | No |
filters_in_url | new | — | Yes | No | No |
external_links_tracking | new | — | Yes | No | No |
enable_ai_chat | new | serverside (Burst\Admin\Abilities_Api\Abilities_Api::should_show_enable_notice()) | Yes | Yes | Yes |
opt-in-sharing | new | — | Yes | No | No |
turbo_mode_recommended | warning | — | Yes | No | No |
mainwp_integration_disabled | warning | serverside (Burst\Admin\Tasks::should_show_mainwp_integration_task()) | Yes | Yes | Yes |
persistent_object_cache_recommended | warning | serverside (Burst\Admin\Statistics\Statistics::should_recommend_object_cache()) | Yes | Yes | No |
wp_consent_api_notice | warning | serverside (Burst\Admin\Tasks::is_wp_consent_api_active()) | Yes | Yes | Yes |
burst_geo_ip_import_error | warning | serverside (wp_option_burst_geo_ip_import_error) | Yes | No | Yes |
Tasks with no condition key have no automatic lifecycle management — they must be added and removed programmatically or they remain active once inserted into burst_tasks.
The external_links_tracking task notifies administrators that external link click tracking is available and points them to Settings > General to manage it. It has no condition key, so it is not added by add_initial_tasks(); instead it is inserted programmatically with add_task( 'external_links_tracking' ) when the plugin is upgraded. Once inserted it stays active until dismissed.
The search_console_integration task notifies administrators that they can connect Google Search Console to Burst and see which search queries bring visitors to their site, directly in the dashboard. It has no condition key, so it is not added by add_initial_tasks(); instead it is inserted programmatically with add_task( 'search_console_integration' ) when the plugin is upgraded. Its url is the internal hash link #/settings/integrations, and it increments the admin-bar badge counter (plusone). Once inserted it stays active until dismissed.
The underlying detection for malicious_data_removal no longer runs directly on burst_daily. Instead, burst_daily schedules a single burst_detect_malicious_data event two minutes in the future, and that event performs the anomaly check and sets/clears the burst_cleanup_uid_visits option. The task's serverside condition (wp_option_burst_cleanup_uid_visits) is unchanged, but the option it reads may lag up to two minutes behind the burst_daily run before the next validation pass reflects it.
The enable_ai_chat task surfaces the Burst AI chat onboarding notice. Its serverside condition calls Burst\Admin\Abilities_Api\Abilities_Api::should_show_enable_notice(), which returns true only when wp_register_ability() is available and the enable_abilities_api option is not yet enabled. The fix value burst_option_enable_abilities_api toggles the enable_abilities_api option directly from the task UI.
The enable_ai_chat task now includes a url pointing to the guides/ask-burst-anything-setting-up-the-ai-chat-for-your-analytics guide on the Burst website. The relative path is resolved against the Burst website URL with UTM parameters appended automatically.
The mainwp_integration_disabled task warns when the MainWP Child plugin is active but Burst's MainWP integration is still disabled. Its serverside condition calls Burst\Admin\Tasks::should_show_mainwp_integration_task(), which returns true only when mainwp-child/mainwp-child.php is installed and active (including network-active on multisite) and the enable_mainwp_integration option is empty. The fix value burst_option_enable_mainwp_integration flips the option from the task UI, the task increments the admin-bar badge counter (plusone), and its url points to the guides/manage-burst-statistics-across-all-your-sites-with-mainwp guide on the Burst website. The relative path is resolved against the Burst website URL with UTM parameters appended automatically.
Pro - AgencyAvailable in the Agency tier
The MainWP integration is an Agency-tier feature. See MainWP integration.
The persistent_object_cache_recommended task warns when Burst detects very slow analytics queries on a site that is not yet running a persistent object cache. Its serverside condition calls Burst\Admin\Statistics\Statistics::should_recommend_object_cache(), which returns false when wp_using_ext_object_cache() reports an external cache is active, and otherwise reads MAX(max_execution_time) from the burst_query_stats table and returns true once the slowest recorded query crosses a threshold (default 10 seconds). The task uses dismiss_permanently = true, so once dismissed it will not be re-added even if slow queries persist. The threshold is filterable:
Show code
add_filter( 'burst_object_cache_recommendation_threshold_seconds', function( float $threshold ): float {
// Recommend a persistent object cache once any analytics query exceeds 5 seconds.
return 5.0;
} );
The wp_consent_api_notice task warns that a configured cookie banner may suppress tracking. Its serverside condition calls Burst\Admin\Tasks::is_wp_consent_api_active(), which returns true when the WP_Consent_API class exists or when Complianz is active (CMPLZ_VERSION or cmplz_version defined). When statistics consent is required by such a banner, Burst will not track any visitor the banner has not flagged as having consented. The task's url deep-links to the wp-consent-api-integration guide.
The burst_geo_ip_import_error task warns that the GeoIP database could not be downloaded, which is required for tracking country information. It is registered on the burst_tasks filter by Burst\Admin\Geo_Ip\Geo_Ip::add_burst_geo_ip_import_error(), which appends the actual error message from the failed import (read from the burst_geo_ip_import_error option) to the message. Its serverside condition (wp_option_burst_geo_ip_import_error) is true only while that option is set. The task is suppressed while the burst_recently_activated transient is present, so a freshly activated site that may still be downloading does not show the notice prematurely. The task's url points to the instructions/geo-ip-error/ guide.
The enable_ai_chat task surfaces the Burst AI chat onboarding notice.
WordPress options
| Option | Type | Description |
|---|---|---|
burst_tasks | array | Active task IDs. Each entry is a sanitize_title()-processed string. |
burst_tasks_permanently_dismissed | array | Task IDs that have been permanently dismissed and will never be re-added. |
Transient:
| Transient | TTL | Description |
|---|---|---|
burst_plusone_count | 1 day | Cached count of active tasks that have plusone = true. Cleared whenever a task is added, on task validation and on dismissal. |
Cron events
| Hook | Schedule | Description |
|---|---|---|
burst_validate_tasks | Single event (30s) | Scheduled by schedule_task_validation(). Evaluates all serverside conditions and syncs burst_tasks. |
burst_detect_malicious_data | Single event (2 min) | Scheduled from burst_daily. Runs the anomaly check that sets the burst_cleanup_uid_visits option feeding the malicious_data_removal task. |
Hooks and filters
burst_tasks
Filters the full array of task definitions before they are used anywhere. Use this filter to add, remove, or modify tasks.
Parameters:
| Parameter | Type | Description |
|---|---|---|
$tasks | array | Indexed array of task definition arrays as described in Task definition fields. |
Example — adding a custom task:
Show code
add_filter( 'burst_tasks', function( array $tasks ): array {
$tasks[] = [
'id' => 'my_custom_task',
'msg' => __( 'Your custom notice message.', 'my-plugin' ),
'icon' => 'warning',
'dismissible' => true,
'condition' => [
'type' => 'serverside',
'function' => 'MyPlugin\Tasks::is_condition_met()',
],
];
return $tasks;
} );
Example — adding a task with a WordPress option condition:
Show code
add_filter( 'burst_tasks', function( array $tasks ): array {
$tasks[] = [
'id' => 'my_option_task',
'msg' => __( 'Something requires your attention.', 'my-plugin' ),
'icon' => 'warning',
'dismissible' => true,
'condition' => [
'type' => 'serverside',
// Active when get_option('my_plugin_error') !== false.
'function' => 'wp_option_my_plugin_error',
],
];
return $tasks;
} );
Example — removing a built-in task:
add_filter( 'burst_tasks', function( array $tasks ): array {
return array_filter( $tasks, fn( $t ) => $t['id'] !== 'ecommerce_integration' );
} );
burst_dismiss_task
Fires when a task is dismissed by the user, before it is removed from burst_tasks.
Parameters:
| Parameter | Type | Description |
|---|---|---|
$task_id | string | The ID of the task being dismissed. |
Example:
Show code
add_action( 'burst_dismiss_task', function( string $task_id ): void {
if ( $task_id === 'my_custom_task' ) {
// Run cleanup when user dismisses your task.
Delete_option( 'my_plugin_error' );
}
} );
Developer API
The Tasks class (Burst\Admin\Tasks) is accessible via burst()->tasks.
get_raw_tasks(): array
Returns the complete task definitions array after applying the burst_tasks filter and resolving URLs. Does not filter by active status.
get_tasks(): array
Returns the filtered, sorted list of tasks for display. Removes tasks not in burst_tasks (except clientside tasks), applies the dismiss_non_error_notices setting, deduplicates by ID, and sorts warnings to the top.
add_task( string $task_id ): void
Inserts a task ID into burst_tasks and clears the burst_plusone_count transient so the badge counter is recalculated on the next read. Has no effect if the task is permanently dismissed.
burst()->tasks->add_task( 'my_custom_task' );
dismiss_task( string $task_id ): void
Removes a task ID from burst_tasks and fires burst_dismiss_task. If the task has dismiss_permanently = true, also adds it to burst_tasks_permanently_dismissed. Clears the burst_plusone_count transient.
burst()->tasks->dismiss_task( 'my_custom_task' );
has_task( string $task_id ): bool
Returns true if the task ID is currently in burst_tasks.
if ( burst()->tasks->has_task( 'my_custom_task' ) ) {
// Task is active.
}
get_task_by_id( string $task_id ): ?array
Returns the task definition array for a given ID, or null if not found.
$task = burst()->tasks->get_task_by_id( 'cron' );
schedule_task_validation(): void
Schedules a single burst_validate_tasks cron event 30 seconds from now, if one is not already scheduled. Always use this instead of calling validate_tasks() directly.
burst()->tasks->schedule_task_validation();
add_initial_tasks(): void
Inserts all activation-type tasks into burst_tasks. Called automatically on plugin activation.
undismiss_task( string $task_id ): bool
Removes a task ID from burst_tasks_permanently_dismissed, allowing it to be re-added by a future validation run. Returns true if the task was found and removed.
burst()->tasks->undismiss_task( 'my_custom_task' );
plusone_count(): int
Returns the number of currently active tasks with plusone = true and icon !== 'success'. Result is cached in the burst_plusone_count transient for one day. Returns 0 if the current user cannot manage Burst.
is_wp_consent_api_active(): bool
Returns true when the WP Consent API or Complianz is active — that is, when the WP_Consent_API class exists or the CMPLZ_VERSION or cmplz_version constant is defined. Used as the serverside condition for the wp_consent_api_notice task.
if ( Burst\Admin\Tasks::is_wp_consent_api_active() ) {
// A consent integration is present.
}
Complete custom task example
Show code
/**
* Register a custom Burst task that warns when a specific option is set.
*/
add_filter( 'burst_tasks', function( array $tasks ): array {
$tasks[] = [
'id' => 'my_plugin_api_warning',
'msg' => __( 'My Plugin: API key is missing. Please configure it in the settings.', 'my-plugin' ),
'icon' => 'warning',
'url' => admin_url( 'options-general.php?page=my-plugin' ),
'dismissible' => true,
'plusone' => true,
'condition' => [
'type' => 'serverside',
// Active when get_option('my_plugin_api_missing') is not false.
'function' => 'wp_option_my_plugin_api_missing',
],
];
return $tasks;
} );
// Set the option to trigger the task, then schedule validation.
Add_action( 'init', function(): void {
if ( get_option( 'my_plugin_api_key' ) === false ) {
update_option( 'my_plugin_api_missing', true );
if ( function_exists( 'burst' ) ) {
burst()->tasks->schedule_task_validation();
}
}
} );
// Clean up when the task is dismissed.
Add_action( 'burst_dismiss_task', function( string $task_id ): void {
if ( $task_id === 'my_plugin_api_warning' ) {
delete_option( 'my_plugin_api_missing' );
}
} );