Goals reference
Goals let you measure conversions in Burst Statistics. Each goal tracks a specific user action — a click, a page visit, or a WordPress hook execution — and records how often it occurs relative to your chosen conversion metric.
Overview
A goal is stored as a row in {prefix}_burst_goals. When a visitor completes a goal, a record is written to {prefix}_burst_goal_statistics linking that pageview to the goal. Goals are represented by the Burst\Frontend\Goals\Goal class and managed in bulk via Burst\Frontend\Goals\Goals. Burst supports two processing paths:
- Client-side — the browser tracking script detects the conversion (click or element view) and includes it in the tracking payload.
- Server-side — PHP detects the conversion (a WordPress hook fires or a page is visited) and writes the statistic directly.
Pro - CreatorAvailable in the Creator tier
The Pro version allows unlimited goals. The free version permits only one goal at a time. If a goal already exists, Goal::save() silently returns false for any new insert on the free version. Learn more about goal conversion tracking
Goal types
Goal types are registered through the field definitions and can be extended with the burst_goal_types filter.
| Type | Tracking path | server_side | Description |
|---|---|---|---|
clicks | Client-side | false | Fires when a visitor clicks an element matching the configured CSS selector. |
views | Client-side | false | Fires when a visitor views an element matching the configured CSS selector. |
visits | Server-side | true | Fires when a visitor lands on the target page. |
hook | Server-side | true | Fires when a specified WordPress action hook executes. |
server_side is derived automatically in Goal::get():
$this->server_side = $this->type === 'hook' || $this->type === 'visits';
Configuration fields
These fields map directly to the goal editor in the admin UI.
title
| Field | Value |
|---|---|
| Type | hidden (set programmatically) |
| Default | false (displays as "New goal" when empty) |
The human-readable name shown in the goals list.
status
| Field | Value |
|---|---|
| Type | hidden (toggled via the goal editor UI) |
| Default | false (inactive) |
| Accepted values | active, inactive |
Controls whether the goal is currently collecting conversions. Setting status to active resets date_start to the current time.
type
| Field | Value |
|---|---|
| Type | radio-buttons |
| Default | clicks |
| Accepted values | clicks, views, visits, hook |
The type of event to track. See Goal types for details on each option.
page_or_website
| Field | Value |
|---|---|
| Type | radio-buttons |
| Default | website |
| Accepted values | page, website |
| Shown for | clicks, views, hook goal types |
Determines whether the goal applies to the entire site or only to a specific page.
| Option | Description |
|---|---|
page | Track only when the conversion happens on a specific page |
website | Track the conversion anywhere on the site |
When website is selected, the stored url value is set to *.
specific_page
| Field | Value |
|---|---|
| Type | select-page |
| Default | false |
| Shown for | visits type, or when page_or_website is page |
The specific page to track. Accepts a relative URL. When page_or_website is website, this field is ignored and url is stored as *.
selector
| Field | Value |
|---|---|
| Type | selector |
| Default | '' (empty string) |
| Shown for | clicks and views goal types |
A CSS selector identifying the element to track. For example: #newsletter-form .submit-btn or .add-to-cart.
The value is sanitized with sanitize_text_field() before storage.
hook
| Field | Value |
|---|---|
| Type | hook |
| Default | '' (empty string) |
| Shown for | hook goal type only |
The WordPress action hook name to listen for. For example: woocommerce_payment_complete or my_plugin_form_submitted.
The value is sanitized with sanitize_text_field() before storage.
Hook-type goals rely on the burst_uid cookie being set by a prior client-side pageview. If the hook fires before the visitor has been tracked (for example, during a server-side-only request), the conversion will not be recorded.
conversion_metric
| Field | Value |
|---|---|
| Type | radio-buttons |
| Default | visitors |
| Accepted values | visitors, sessions, pageviews |
Determines the denominator used when calculating the conversion rate.
| Option | Description |
|---|---|
visitors | Conversions ÷ unique visitors |
sessions | Conversions ÷ total sessions |
pageviews | Conversions ÷ total pageviews |
Goal object
The Burst\Frontend\Goals\Goal class represents a single goal. Properties are read/write via magic __get / __set.
| Property | Type | Default | Description |
|---|---|---|---|
id | int | 0 | Database primary key (ID column). |
title | string | '' | Human-readable goal name. Defaults to "New goal" when empty. |
type | string | 'clicks' | Goal type slug. See Goal types. |
status | string | 'inactive' | 'active' or 'inactive'. |
server_side | bool | false | Set automatically to true when type is 'hook' or 'visits'. Derived at load time — not stored as a separate column. |
url | string | '*' | Raw URL stored in the database. '*' means site-wide. |
page_or_website | string | 'website' | Derived from url. 'website' when url === '*'; 'page' otherwise. |
specific_page | string | '' | Relative URL used when page_or_website === 'page'. Derived from url. |
conversion_metric | string | 'visitors' | How conversions are counted. |
selector | string | '' | CSS selector for clicks and views goal types. |
hook | string | '' | WordPress action name for hook goal type. |
date_start | int | — | Unix timestamp when the goal became active. Reset each time status changes to 'active', or on first creation. |
date_end | int | 0 | Unix timestamp when tracking ended. 0 means still running. |
date_created | int | 0 | Unix timestamp of first insertion. |
Deprecated properties
The following properties were deprecated in v2.0.0 and may be removed in a future release. Do not use them in new code.
| Property | Type | Replacement |
|---|---|---|
attribute | ?string | Use selector instead |
attribute_value | ?string | Use selector instead |
Tracking lifecycle
Client-side goals (clicks, views)
- The visitor interacts with an element matching the goal's
selector. - The frontend goals script appends the goal ID to the
completed_goalsarray in the tracking payload. - The tracking endpoint receives the payload and records the conversion in
{prefix}_burst_goal_statistics.
Server-side goals — hook type
- During the WordPress
initaction,Goals_Tracker::add_dynamic_hooks()reads every activehook-type goal and registers a WordPress action for each goal'shookproperty. - When that action fires,
Goals_Tracker::handle_hook( $hook_name )runs:- Reads the
burst_uidcookie to identify the visitor. - If no
burst_uidis present, the conversion is not recorded. - Retrieves the visitor's most recent statistic row via
get_last_user_statistic(). - If the goal is scoped to a specific page (
page_or_website === 'page'), checks thatspecific_pageappears in the storedpage_url + parametersstring. - Calls
create_goal_statistic()to write the conversion.
- Reads the
Show code
// Trigger a custom hook-type goal.
// 1. In Burst, create a goal with type = 'hook' and hook = 'my_plugin_form_submitted'.
// 2. Fire the action from your plugin:
do_action( 'my_plugin_form_submitted' );
// Goals_Tracker picks up the action and records the conversion
// for the currently identified visitor.
Server-side goals — visits type
Burst detects the target page URL server-side and records a conversion when the visitor lands on the matching URL.
Goal conversion queries
Internally, Goal_Statistics::get_goal_completed_count_sql() builds the SQL used to count goal completions. As of v3.3.0, this query JOINs {prefix}_burst_sessions so that session-level attributes such as device_id are read from the sessions table rather than the statistics table.
:::caution Breaking change
Changed in v3.3.0: device_id (and the related browser_id, platform_id, browser_version_id, first_time_visit, and bounce columns) have moved from {prefix}_burst_statistics to {prefix}_burst_sessions. Any custom SQL that queries goal conversions and references these columns by statistics.device_id (or without a table qualifier) must be updated to JOIN {prefix}_burst_sessions and reference sessions.device_id instead.
:::
The generated SQL now takes the following form:
Show code
// Simplified representation of the query produced by get_goal_completed_count_sql().
global $wpdb;
$sql = $wpdb->prepare(
"SELECT COUNT(DISTINCT statistics.uid) AS value
FROM {$wpdb->prefix}burst_statistics AS statistics
INNER JOIN {$wpdb->prefix}burst_goal_statistics AS goals
ON statistics.ID = goals.statistic_id
INNER JOIN {$wpdb->prefix}burst_sessions AS sessions
ON statistics.session_id = sessions.ID
WHERE goals.goal_id = %s
AND statistics.time > %s",
$goal_id,
$date_start
);
The device-breakdown query used to determine the best-performing device for a goal also references sessions.device_id:
Show code
// Pageviews per device — sessions JOIN required since device_id moved to burst_sessions.
$sql = $wpdb->prepare(
"SELECT COUNT(statistics.uid) AS value, sessions.device_id
FROM {$wpdb->prefix}burst_statistics AS statistics
INNER JOIN {$wpdb->prefix}burst_sessions AS sessions
ON statistics.session_id = sessions.ID
WHERE statistics.time > %s
GROUP BY sessions.device_id
ORDER BY value DESC
LIMIT 4",
$date_start
);
Database tables
| Table | Purpose |
|---|---|
{prefix}_burst_goals | One row per goal; stores all goal configuration. |
{prefix}_burst_goal_statistics | Many-to-many join between statistic rows and goal IDs. All rows for a goal are deleted when the goal is deleted. |
Tables are created via the burst_install_tables action. See burst_install_tables.
Predefined goals
Pro - CreatorAvailable in the Creator tier
Integrations can register predefined goal templates. These are surfaced in the goals UI when the corresponding third-party plugin is active. Learn more about goal conversion tracking
Goals::get_predefined_goals() collects goal templates from each registered integration and returns them as a flat list.
Show code
/**
* @param bool $skip_active_check Pass true to include goals from inactive integration plugins.
* @return array<int, array{
* id: string,
* type: string,
* description: string,
* status: string,
* server_side: bool,
* url: string,
* hook: string
* }>
*/
$predefined = burst_loader()->frontend->goals->get_predefined_goals();
By default only goals from active integration plugins are returned.
A predefined goal template can be saved with Goal::add_predefined( string $id ):
$goal = new \Burst\Frontend\Goals\Goal();
$new_id = $goal->add_predefined( 'woocommerce-purchase' );
// Returns the new goal ID on success, or 0 on failure.
add_predefined() sets status = 'active', conversion_metric = 'visitors', and url = '*' as defaults before calling save().
Available predefined goals by integration
| Integration | Goal ID | Type | Trigger |
|---|---|---|---|
| Elementor | elementor_pro_forms_form_submitted | hook | elementor_pro/forms/form_submitted |
| Elementor | submit_button_click | clicks | .elementor-field-type-submit .elementor-button |
| WooCommerce | woocommerce_add_to_cart | hook | woocommerce_add_to_cart |
| WooCommerce | woocommerce_checkout_order_created | hook | woocommerce_checkout_order_created |
| WooCommerce | woocommerce_payment_complete | hook | woocommerce_payment_complete |
| WooCommerce | woocommerce_add_to_cart_click | clicks | .add_to_cart_button |
| WooCommerce | woocommerce_click_checkout_button | clicks | .wc-block-cart__submit-button |
| Easy Digital Downloads | edd_complete_purchase | hook | edd_complete_purchase |
| Easy Digital Downloads | edd_add_to_cart | clicks | .edd-add-to-cart |
| Easy Digital Downloads | edd_go_to_checkout | clicks | .edd_go_to_checkout |
| Easy Digital Downloads | edd_click_purchase | clicks | #edd-purchase-button |
Querying goals
Show code
$goals = burst_loader()->frontend->goals->get_goals( [
'status' => 'active', // 'active', 'inactive', or 'all' (default)
'limit' => 10, // default: 9999
'offset' => 0, // default: 0
'orderby' => 'ID', // any column in burst_goals; default: 'ID'
'order' => 'ASC', // 'ASC' or 'DESC'; default: 'ASC'
'date_start' => strtotime( '-30 days' ), // Unix timestamp; -1 = no filter (default)
'date_end' => time(), // Unix timestamp; default: time()
] );
foreach ( $goals as $goal ) {
echo $goal->id . ': ' . $goal->title . ' (' . $goal->type . ')';
}
date_start and date_end filter on date_created. The orderby value is validated against the actual columns of burst_goals; unknown values fall back to 'ID'.
Saving and deleting goals
Creating a new goal
Show code
$goal = new \Burst\Frontend\Goals\Goal();
$goal->title = 'Newsletter signup';
$goal->type = 'clicks';
$goal->selector = '#newsletter-form .submit-btn';
$goal->status = 'active';
$success = $goal->save();
echo $goal->id; // populated after a successful insert
Updating an existing goal
$goal = new \Burst\Frontend\Goals\Goal( 42 );
$goal->status = 'inactive';
$goal->save();
Deleting a goal
$goal = new \Burst\Frontend\Goals\Goal( 42 );
$goal->delete(); // removes the goal row AND all burst_goal_statistics rows for this goal
Save behaviour
title,selector, andhookare sanitized withsanitize_text_field().urlis sanitized as a relative URL. Whenpage_or_website === 'website'the stored value is forced to'*'.server_sideis derived from the goal type definition — not settable by the caller.date_startis set totime()on first creation or wheneverstatuschanges to'active'.- Returns
trueon success,falseon failure (including exceeding the free-tier goal limit).
REST API endpoints
All goals endpoints are under the burst/v1 namespace and require a valid nonce.
| Endpoint | Method | Permission | Description |
|---|---|---|---|
burst/v1/goals/get | GET | view | Returns all configured goals and the list of predefined goals. |
burst/v1/goals/add | POST | manage | Creates a new goal. |
burst/v1/goals/set | POST | manage | Updates an existing goal. |
burst/v1/goals/delete | POST | manage | Deletes a goal and its associated statistics. |
burst/v1/goals/add_predefined | POST | manage | Adds a predefined goal from an integration. |
burst/v1/data/goals | GET | view | Returns goal conversion statistics for the selected date range. |
burst/v1/data/live-goals | GET | view | Returns live goal conversion counts (since midnight). |
Permission levels:
view— requiresview_burst_statisticscapabilitymanage— requiresmanage_burst_statisticscapability (typically administrators)
Hooks and filters
burst_goal_types
Filter the available goal type definitions. Controls which types appear in the goal editor and are accepted by Goal::save().
Parameters:
| Parameter | Type | Description |
|---|---|---|
$types | array | Associative array of goal type definitions keyed by type slug. Each entry may include label, description, icon, and server_side. |
Example:
Show code
add_filter( 'burst_goal_types', function( array $types ): array {
$types['video_play'] = [
'label' => __( 'Video play', 'my-plugin' ),
'description' => __( 'Fires when a video starts playing.', 'my-plugin' ),
'server_side' => false,
];
return $types;
} );
burst_allowed_goal_types
Filters the normalized list of goal type slugs accepted by Burst's sanitization layer.
Use this alongside burst_goal_types when you introduce a custom type and want it to survive request validation.
Parameters:
| Parameter | Type | Description |
|---|---|---|
$goal_types | string[] | Allowed goal type slugs. |
Example:
Show code
add_filter( 'burst_allowed_goal_types', function( array $goal_types ): array {
$goal_types[] = 'video_play';
return array_values( array_unique( $goal_types ) );
} );
burst_before_save_goals
Fires immediately before a goal is written to the database (both insert and update).
Parameters:
| Parameter | Type | Description |
|---|---|---|
$goal | \Burst\Frontend\Goals\Goal | The Goal object about to be saved. Public properties can be read or mutated. |
Example:
Show code
add_action( 'burst_before_save_goals', function( \Burst\Frontend\Goals\Goal $goal ): void {
if ( $goal->type === 'hook' && empty( $goal->hook ) ) {
$goal->hook = 'woocommerce_thankyou';
}
} );
burst_after_save_goals
Fires after a goal has been successfully saved and the object refreshed from the database. Does not fire when save() returns false.
Parameters:
| Parameter | Type | Description |
|---|---|---|
$goal | \Burst\Frontend\Goals\Goal | The saved Goal object with current database values, including the new id for inserts. |
Example:
Show code
add_action( 'burst_after_save_goals', function( \Burst\Frontend\Goals\Goal $goal ): void {
if ( $goal->status === 'active' ) {
my_crm_sync_goal( $goal->id, $goal->title );
}
} );
burst_install_tables
Action fired by the Burst installer to trigger database table creation. Goals hooks into this at priority 10 to create {prefix}_burst_goals.
Parameters: none.
Example:
// Force table creation, e.g. after a manual reset.
do_action( 'burst_install_tables' );
burst_goal_fields
Filters the goal-editor field schema used by the admin app.
Use this to alter the fields shown for goal creation/editing, including adding custom controls or removing unsupported ones.
Parameters:
| Parameter | Type | Description |
|---|---|---|
$fields | array | Goal field definitions loaded from goal-fields.php. |
burst_after_updated_goals
Fires after goal collections are updated through the REST API, including add, update, and delete flows handled by the admin app.
This is broader than burst_after_save_goals, which fires per-goal on model save.
Parameters: none.
Example:
add_action( 'burst_after_updated_goals', function(): void {
my_plugin_refresh_goal_dependent_cache();
} );