Skip to main content

Reports

The reporting system in Burst Statistics allows you to create, schedule, and send analytics reports via email. Reports can be sent on a daily, weekly, or monthly schedule, and support two formats: a classic email with data tables, and a "story" format with a link to a shareable dashboard.


Overview

Reports are stored in the {prefix}burst_reports database table. Each report has a set of content blocks, a list of email recipients, a frequency, and a delivery schedule. When a scheduled report is due, it is dispatched via WP-Cron using a batched email queue, with delivery status tracked in a separate {prefix}burst_report_logs table.

Pro

The full reporting system (scheduled reports, multiple formats, content blocks, delivery logs) is a Pro feature.

Learn more about automated reporting exports


Database Tables

{prefix}burst_reports

Stores report configuration.

ColumnTypeDescription
IDint unsignedAuto-incremented primary key
namevarchar(255)Report display name
date_rangevarchar(255)The date range used for report data
formatvarchar(32)Report format (classic or story)
frequencyvarchar(16)Send frequency (daily, weekly, monthly)
fixed_end_datevarchar(16)Fixed end date (Y-m-d) used as the data range end
day_of_weekvarchar(16)Day of week for weekly/monthly reports (e.g. monday)
week_of_monthintOccurrence of the weekday in the month (1–4, or -1 for last)
send_timevarchar(16)Time to send the report in HH:MM format (site timezone)
last_editint unsignedUnix timestamp of last modification
enabledtinyint(1)Whether the report is active
scheduledtinyint(1)Whether the report is sent automatically on schedule
contentlongtextJSON-encoded array of content block definitions
recipientslongtextJSON-encoded array of recipient email addresses

{prefix}burst_report_logs

Tracks report delivery history.

ColumnTypeDescription
IDbigint unsignedAuto-incremented primary key
report_idbigint unsignedAssociated report ID
queue_idvarchar(32)Date-based queue identifier (Y-m-d, or test-Y-m-d-{timestamp} for test sends)
batch_idint unsignedBatch number (null for parent/queue-level log entries)
statusvarchar(32)Delivery status string
messagetextHuman-readable status message
timeint unsignedUnix timestamp of the log entry
datevarchar(10)Date string extracted from queue ID (Y-m-d)

Report Formats

The format field on a report controls how the email is constructed.

ValueDescription
classicFull HTML email with data tables for each content block
storyShort teaser email with a button linking to a shareable story dashboard

Report Frequency

The frequency field controls how often a scheduled report is sent.

ValueDescription
dailySent every day at the configured send_time
weeklySent on the configured day_of_week each week
monthlySent on the nth occurrence of day_of_week within each month, determined by week_of_month

For monthly reports, week_of_month accepts 14 for the first through fourth occurrence of the weekday, or -1 for the last occurrence.


Report Date Ranges

The date_range (or reportDateRange) field on a report defines which period the report data covers.

Accepted values are defined by the Report_Date_Range domain type. The default when creating a report from onboarding is last_week.


Content Blocks

Each report contains a content array of block definitions. For the classic format, these blocks map to data table sections rendered in the email.

Block objects stored in the content field have the following structure:

PropertyTypeDescription
idstringBlock identifier (must be a valid Report_Content_Block ID)
filtersarrayQuery filters applied to this block's data
contentstringOptional custom text content
date_rangestringOptional per-block date range override
date_range_enabledboolWhether the per-block date range override is active
fixed_end_datestringPer-block fixed end date (Y-m-d)
comment_titlestringOptional comment block title
comment_textstringOptional comment block body text

The compare block (identified by Report_Content_Block::COMPARE) is handled specially: it renders a summary table comparing pageviews, sessions, visitors, and bounce rate against the previous period.


Scheduling

The burst_every_hour cron hook triggers Reports::maybe_send_report(), which checks all enabled scheduled reports. A report is eligible to send when the current time falls within the report's scheduled send window for the day (within a 24-hour grace window after the scheduled timestamp). Eligible reports are dispatched via wp_schedule_single_event using the burst_send_email_batch hook, scheduled 5 minutes in the future.

Actual email sending happens in Reports::handle_email_batch(), which processes one batch of up to 10 recipients per cron run. If a report has more recipients than the batch size, additional batches are automatically scheduled 5 minutes apart.


REST API Endpoints

GET /wp-json/burst/v1/reports

Returns all reports, ordered by last edit date. Requires manage-level access and a valid burst_nonce nonce parameter.

Response:

{
"request_success": true,
"data": {
"reports": [ { ... } ]
}
}

POST /wp-json/burst/v1/do_action/report/{action}

Performs a write action on a report. Requires admin access. The {action} segment maps to one of the following actions (prefixed with report- internally):

Action pathDescription
createCreate a new report
deleteDelete an existing report
updateUpdate an existing report
send-test-reportSend a test email immediately
send-report-nowSend the report immediately and schedule the queue
previewGet a preview HTML render of the report

GET /wp-json/burst/v1/report/logs

Returns aggregated delivery logs for the past 30 days. Requires manage-level access and a valid burst_nonce nonce parameter.

Response:

{
"request_success": true,
"data": {
"logs": [ { ... } ]
}
}

Delivery Status Values

The following status values appear in the burst_report_logs table and are returned in the lastSendStatus field of a report object.

StatusDescription
processingQueue has been created and email sending is scheduled
sending_successfulAll recipients received the email
sending_failedAll emails in the batch failed to send
partly_sentSome emails were sent, some failed
cron_missThe scheduled cron event did not fire within the expected window
scheduledReport is enabled and scheduled but has not sent yet
ready_to_shareReport is not scheduled; the shareable story link is ready
conceptReport is scheduled but currently disabled
Breaking change

Changed in v3.3.0: The status value ready_to_send has been replaced by ready_to_share. The condition that triggers this status has also changed: previously it was returned only for reports with format = story; it is now returned for any report where scheduled = false, regardless of format.

Any consumer of the reports REST response that checks for "lastSendStatus": "ready_to_send" must be updated to check for "ready_to_share" instead.


Hooks and Filters

burst_email_blocks

Filters the list of available content blocks used to populate the classic email report.

Parameters:

ParameterTypeDescription
$blocksarrayArray of block definitions loaded from includes/Admin/Mailer/config/blocks.php

Example:

add_filter( 'burst_email_blocks', function( array $blocks ): array {
// Add a custom block definition.
$blocks['my_custom_block'] = [
'title' => __( 'Top Custom Metric', 'my-plugin' ),
'header' => [ __( 'Label', 'my-plugin' ), __( 'Value', 'my-plugin' ) ],
'url' => '#/statistics',
'query_args' => [
'metrics' => [ 'my_metric' ],
'type' => 'my_type',
],
];
return $blocks;
} );

burst_mail_report_limit

Filters the maximum number of rows returned per content block in a classic email report.

Parameters:

ParameterTypeDescription
$limitintNumber of rows. Default: 5

Example:

add_filter( 'burst_mail_report_limit', function( int $limit ): int {
return 10;
} );

burst_mail_report_results

Filters the raw query results for a content block before they are processed into the email table.

Parameters:

ParameterTypeDescription
$raw_resultsarrayArray of result rows from the statistics query
$qdQuery_DataThe query data object used for the block
$start_dateintUnix timestamp of the report period start
$end_dateintUnix timestamp of the report period end

Example:

add_filter( 'burst_mail_report_results', function( array $results, $qd, int $start, int $end ): array {
// Remove rows where the first column is empty.
return array_filter( $results, fn( $row ) => ! empty( reset( $row ) ) );
}, 10, 4 );

burst_mail_reports_blocks

Filters the fully built blocks array before it is passed to the Mailer for rendering in a classic report. This runs after each block's data has been fetched and formatted.

Parameters:

ParameterTypeDescription
$blocksarrayAssociative array of built block data keyed by block ID
$date_startintUnix timestamp of the report period start
$date_endintUnix timestamp of the report period end

Example:

add_filter( 'burst_mail_reports_blocks', function( array $blocks, int $start, int $end ): array {
// Remove the compare block from all reports.
unset( $blocks['compare'] );
return $blocks;
}, 10, 3 );

burst_email_template

Filters the path to the main HTML email template file.

Parameters:

ParameterTypeDescription
$pathstringAbsolute path to the email template file

Example:

add_filter( 'burst_email_template', function( string $path ): string {
return get_stylesheet_directory() . '/burst/email.html';
} );

burst_email_block_template

Filters the path to the HTML template used to render each content block within the email.

Parameters:

ParameterTypeDescription
$pathstringAbsolute path to the block template file

Example:

add_filter( 'burst_email_block_template', function( string $path ): string {
return get_stylesheet_directory() . '/burst/block.html';
} );

burst_email_readmore_template

Filters the path to the HTML template used to render the "read more" section at the bottom of the email.

Parameters:

ParameterTypeDescription
$pathstringAbsolute path to the read-more template file

Example:

add_filter( 'burst_email_readmore_template', function( string $path ): string {
return get_stylesheet_directory() . '/burst/read-more.html';
} );

burst_report_log_delete_threshold

Filters how many days of report delivery logs are retained before old entries are purged.

Parameters:

ParameterTypeDescription
$daysintNumber of days to retain logs. Default: 30

Example:

add_filter( 'burst_report_log_delete_threshold', function( int $days ): int {
return 90;
} );

burst_create_report_from_onboarding (action)

Fired during onboarding to automatically create a default weekly summary report for a given email address.

Parameters:

ParameterTypeDescription
$emailstringThe recipient email address for the onboarding report

The default report created by this action has the following settings:

SettingDefault value
Name"Weekly Summary"
Formatclassic
Frequencyweekly
Day of weekmonday
Send time09:00
Date rangelast_week
Enabledtrue
Scheduledtrue

burst_send_email_batch (action)

WP-Cron hook that fires to process a single batch of emails for a report queue.

Parameters:

ParameterTypeDescription
$report_idintThe report ID
$queue_idstringThe queue identifier (date string or test queue ID)
$batch_idint|nullThe batch number (1-based)
caution

Do not call or schedule burst_send_email_batch directly. Use the report-send-report-now REST action or the admin UI instead. Manually scheduling duplicate events for the same [$report_id, $queue_id, $batch_id] combination is a no-op because the system checks for existing scheduled events and already-processed queue entries before sending.


Email Template Variables

The main email template (email.html) supports the following placeholder tokens:

TokenDescription
{base}HTML <base> tag pointing to the site home URL
{title}Email heading (HTML allowed)
{logo}Light-mode logo image URL
{logo_dark}Dark-mode logo image URL
{message}Introductory message text (e.g. date range coverage)
{blocks}Rendered HTML for all content blocks
{read_more}Rendered HTML for the "read more" section
{sent_by_text}Footer unsubscribe / sender attribution text
{domain}Site home URL

Each block within the block.html template supports:

TokenDescription
{title}Block heading
{subtitle}Block subheading (e.g. "vs. previous week")
{table}Rendered HTML table rows
{url}"Learn more" link URL
{learn-more}"Learn more" button text

The read-more.html template supports:

TokenDescription
{title}Section heading
{message}Teaser text
{read_more_url}Call-to-action button URL
{read_more_text}Call-to-action button label

Report Object Fields (API)

The to_array() method on a Report instance returns the following fields, as used in REST API responses.

Changed in v3.3.0: The Report constructor now accepts a second parameter bool $is_shared_link = false. When true, scheduling and recipient fields are replaced with safe defaults in the returned array, and if the report is disabled to_array() returns an empty array [] instead.

// Instantiate a report for a shared-link context (omits scheduling/recipient data).
$report = new Report( $report_id, true );
$data = $report->to_array(); // Returns [] if report is disabled.

// Standard instantiation (full data, used in admin/REST contexts).
$report = new Report( $report_id );
$data = $report->to_array();
FieldTypeDescription
idint|nullReport ID
namestringReport name
formatstringReport format (classic or story)
enabledboolWhether the report is active
contentarrayArray of content block definitions
reportDateRangestringDate range identifier
fixedEndDatestringFixed end date (Y-m-d)
frequencystringReport frequency (omitted for shared-link requests; defaults to Report_Frequency::DEFAULT)
weekOfMonthint|nullWeek of month for monthly reports (omitted for shared-link requests)
dayOfWeekstring|nullDay of week for weekly/monthly reports (omitted for shared-link requests)
sendTimestringScheduled send time (HH:MM) (omitted for shared-link requests)
lastEditintUnix timestamp of last modification (omitted for shared-link requests)
scheduledboolWhether the report sends automatically (omitted for shared-link requests)
recipientsarrayArray of recipient email addresses (omitted for shared-link requests)
lastSendStatusstringStatus string from the most recent delivery log (omitted for shared-link requests)
lastSendMessagestringHuman-readable message for lastSendStatus (omitted for shared-link requests)

Changed in v3.3.0: For shared-link requests ($is_shared_link = true), the fields marked above are replaced with empty/default values and are not populated from the database. If the report's enabled flag is false, to_array() returns [].


Email Delivery Details

  • Emails are sent using WordPress's wp_mail() function with Content-Type: text/html; charset=UTF-8.
  • Before sending, the recipient domain is validated via DNS MX/A record lookup. Emails to domains with no valid DNS records are skipped and logged as failures.
  • Recipients are processed in batches of 10 (default). Each batch is scheduled as a separate burst_send_email_batch cron event, 5 minutes apart.
  • Duplicate batch processing is prevented: the system checks both existing cron events and the burst_report_logs table before scheduling or sending.
  • The fixed_end_date on a scheduled report is automatically updated to yesterday each time the report is sent, anchoring the data range end date.
  • Test reports (sent via the "Send test" button) are delivered immediately without scheduling a cron event, and their queue IDs use the format test-Y-m-d-{timestamp} to distinguish them from scheduled sends in the logs.
caution

Report delivery depends on WP-Cron. On sites with infrequent traffic or disabled WP-Cron, scheduled reports may be delayed or missed entirely. Missed sends are recorded in the logs with the cron_miss status. Consider configuring a real system cron job to trigger wp-cron.php on a regular interval.