Skip to main content

Goals

Goals let you track conversions in Burst Statistics — clicks, page visits, hook triggers, and more. Each goal stores its own conversion data so you can measure performance over a defined date range.

Overview

A goal is a database record in {prefix}_burst_goals. When a visitor completes a goal, a row is written to {prefix}_burst_goal_statistics linking the pageview statistic to the goal. Burst ships two goal-processing paths:

  • Client-side — the browser tracking script detects the conversion (click, visit) and reports it in the tracking payload.
  • Server-side — PHP detects the conversion (a WordPress action hook fires) and writes the statistic directly.

Goals are represented by the Burst\Frontend\Goals\Goal class and managed in bulk via Burst\Frontend\Goals\Goals.


Goal Object

The Burst\Frontend\Goals\Goal class represents a single goal. Properties are read/write via magic __get / __set.

PropertyTypeDefaultDescription
idint0Database primary key (ID column).
titlestring''Human-readable goal name. Defaults to "New goal" when empty.
typestring'clicks'Goal type slug. See Goal Types.
statusstring'inactive''active' or 'inactive'.
server_sideboolfalseSet automatically to true when type is 'hook' or 'visits'. Derived at load time — not stored as a separate column.
urlstring'*'Raw URL value stored in the database. '*' means site-wide.
page_or_websitestring'website'Derived from url. 'website' when url === '*'; 'page' otherwise.
specific_pagestring''Relative URL used when page_or_website === 'page'. Derived from url.
conversion_metricstring'visitors'How conversions are counted.
selectorstring''CSS selector for click-type goals.
hookstring''WordPress action name for hook-type goals.
date_startintUnix timestamp when the goal became active. Reset each time status changes to 'active', or on first creation.
date_endint0Unix timestamp when tracking ended. 0 means still running.
date_createdint0Unix timestamp of first insertion.

Deprecated Properties

caution

The following properties were deprecated in v2.0.0 and may be removed in a future release. Do not use them in new code.

PropertyTypeReplacement
attribute?stringUse selector instead.
attribute_value?stringUse selector instead.

Goal Types

Goal types are registered through the field definitions and can be extended with the burst_goal_types filter.

TypeTracking pathserver_sideDescription
clicksClient-sidefalseFires when a visitor clicks an element matching selector.
visitsServer-sidetrueFires when a visitor lands on the target URL.
hookServer-sidetrueFires when a specified WordPress action hook executes.

server_side is derived automatically in Goal::get():

$this->server_side = $this->type === 'hook' || $this->type === 'visits';

Free vs Pro: Goal Limits

Pro

The Pro version allows unlimited goals. The free version permits only one goal at a time. If a goal already exists in the database, Goal::save() silently returns false for any new insert on the free version. Learn more about goal conversion tracking


Tracking Lifecycle

Client-side goals (e.g. clicks)

  1. The visitor interacts with an element matching the goal's selector.
  2. The frontend goals script appends the goal ID to the completed_goals array in the tracking payload.
  3. The tracking endpoint receives the payload and records the conversion in {prefix}_burst_goal_statistics.

Server-side goals — hook type

  1. During the WordPress init action, Goals_Tracker::add_dynamic_hooks() reads every active hook-type goal and registers a WordPress action for each goal's hook property.
  2. When that action fires, Goals_Tracker::handle_hook( $hook_name ) runs:
    • Reads the burst_uid cookie to identify the visitor.
    • If no burst_uid is 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 that specific_page appears in the stored page_url + parameters string.
    • Calls create_goal_statistic() to write the conversion.
// 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.
caution

Hook-type goals rely on the burst_uid cookie being set by a prior client-side pageview. If the cookie is absent (e.g. the form was submitted without a preceding tracked pageview), the conversion will not be recorded.


Database Tables

TablePurpose
{prefix}_burst_goalsOne row per goal; stores all goal configuration.
{prefix}_burst_goal_statisticsMany-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.


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.

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:

// 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:

// 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
);

Predefined Goals

Integrations can register predefined goal templates. Goals::get_predefined_goals() collects the goals array from each registered integration and returns them as a flat list.

/**
* @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().

Pro

Predefined goals that depend on third-party plugin integrations are only surfaced when those plugins are active. Adding any goal requires the manage_burst_statistics capability. Upgrade to Burst Pro


Querying Goals

$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

$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 notes

  • title, selector, and hook are sanitized with sanitize_text_field().
  • url is sanitized as a relative URL. When page_or_website === 'website' the stored value is forced to '*'.
  • server_side is derived from the goal type definition — not settable by the caller.
  • date_start is set to time() on first creation or whenever status changes to 'active'.
  • Returns true on success, false on failure (including exceeding the free-tier goal limit).

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:

ParameterTypeDescription
$typesarrayAssociative array of goal type definitions keyed by type slug. Each entry may include label, description, icon, and server_side.

Example:

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_before_save_goals

Fires immediately before a goal is written to the database (both insert and update).

Parameters:

ParameterTypeDescription
$goal\Burst\Frontend\Goals\GoalThe Goal object about to be saved. Public properties can be read or mutated.

Example:

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:

ParameterTypeDescription
$goal\Burst\Frontend\Goals\GoalThe saved Goal object with current database values, including the new id for inserts.

Example:

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' );