Skip to content

"Worker" scheduled event email report generation and email sending logic #11278

@benbowler

Description

@benbowler

Feature Description

This ticket encompasses the email sending logic, but does not include the HTML template which will be worked on and implemented in separate issues. This issue focusses on retrieving report data, creating a basic (un-styled or minimally styled) HTML email containing this report data and sending using WP mail infrastructure.

  • Within the scheduled event, get report create and send a MVP HTML email with key report data
  • No styling or layout considerations required simply the sending and batching logic
  • Track success or failure in the post type

Do not alter or remove anything below. The following sections will be managed by moderators only.

Acceptance criteria

  • The "Worker" (implemented in 11547) should be extended to perform the report generation and sending process so it handles:
    • Generate report, assemble email template and send the email for each user in the batch using infrastructure implemented in 11566
    • Update the CPT post status:
      • If successfully sent, update the post status to sent and update the post_date.
      • If sending fails, update the post status to failed and store any errors returned within the CPT post meta error_details.
    • Clear the transient googlesitekit_email_reporting_worker_lock transient if present
  • Subscribers receive the email report with live, up-to-date metrics on their chosen cadence (weekly, monthly, quarterly); unsubscribed users receive none; feature disabled = no sends.
  • Content reflects the subscriber’s permissions:
    • Admins: data from modules active on the site.
    • View-only: only modules shared with that user via Dashboard Sharing.
    • Unavailable/recoverable modules or empty sections are omitted cleanly without visual gaps.
      • Any single report failure causes the entire report; no email is sent.
      • If no module data is available, no email is sent.
  • The template renders identically to the mock-based version, now populated by live data

Implementation Brief

  • Update includes/Core/Email_Reporting/Email_Reporting.php to instantiate the full pipeline and pass them into Worker_Task:
  • Extend Worker_Task::handle_worker_action()
    • Within existing $pending_ids loop, for each pending post:
      • Fetch raw payload with $data_requests->get_user_payload( $user_id, $date_range ). - $user_id can be extracted from the post, it will be set as the post author. And $date_range from Email_Log::get_date_range_from_log
        • On WP_Error, call mark_failed( $post_id, $error ) and continue.
      • Build sections with Email_Report_Section_Builder::build_sections( $raw_payload, $frequency, get_user_locale( $user_id ) ). If empty, mark failed (reason: no data) and continue. Error handling should be also covered as section building can throw an error - in this case omit sending the email for current user
      • Assemble/build the email template via Google\Site_Kit\Core\Email_Reporting\Email_Template_Renderer::render() by passing the sections previously built with Email_Report_Section_Builder as the $data argument. On error, mark failed.
      • Send email using $email_sender->send( $to, $subject, $html_body ), where $subject can assembled via a helper method. And for subject use Your performance at a glance for {sitename.com} (and if it is the multisite setup with subdirectories, then we should add site's directory as well).
        • On success: mark_sent( $post_id ) – update status to sent, clear error_details, update post_date/post_date_gmt.
        • On failure: mark_failed( $post_id, $error_or_false ).
      • Remove googlesitekit_email_reporting_worker_lock_{$frequency} transient if present
  • Add helper methods inside Worker_Task:
    • mark_failed( $post_id, WP_Error|string $error ): set status failed, store serialized error in Email_Log::META_ERROR_DETAILS.
      • Use Email_Log_Batch_Query::update_status() and update_post_meta() for status/meta updates.
    • mark_sent( $post_id ): set status sent, delete error_details, update timestamps.
    • build_subject( $frequency ): centralize subject formatting/localization.
      • For example - $subject = sprintf( __( 'Your %s Site Kit report for %s', 'google-site-kit' ), $frequency, $site_domain )

Test Coverage

  • Update existing tests for the Worker_Task class to cover new scenarios:
    • Happy path: mock all collaborators so data requests > sections > template > email send succeed; assert CPT status becomes sent, post_date updates, error_details cleared, and lock is deleted.
    • Data request failure: return WP_Error from get_user_payload(), ensure mark_failed() runs and worker continues to the next post.
    • Empty sections: return empty array from build_sections(); confirm the post is marked failed with “no data” error.
    • Template render failure: make render_template() return WP_Error; post should be marked failed.
    • Send failure: stub Email::send() to return WP_Error; verify CPT status failed and meta updated.
    • Lock cleanup: regardless of outcome, delete_transient( 'googlesitekit_email_reporting_worker_lock_{frequency}' ) is called once at the end.

QA Brief

  • Install a plugin for seeing the CRON events, like WP Crontrol
  • Setup Site Kit (initially with oi.ie to follow the sections that are expected to be present - have data) and run the scenarios

Scenario 1

  • As an Admin do not install any module, default one is only active - Search Console
  • Subscribe to Email Reporting from User Menu dropdown. Pick any frequency, for example I will be using Weekly
  • Go to Tools > Cron Events and find initiator CRON with argument "Weekly". Click Run now on it, it will spawn a worker CRON scheduled to run in 59s
  • (Optional) Go to the database, under wp_posts table, when sorting data by post ID (descending) you should see a new empty post with status gsk_email_scheduled, and in wp_postmeta you will see meta data attached to that post ID _batch_id, _frequency etc
  • You can wait for 1min for worker CRON to execute or also trigger it with Run now
  • You should receive Email matching the Figma design for SC only Figma

Scenario 2

  • As an admin activate and setup Analytics module (this will make it to 2 active modules with reports - Analytics and Search Console)
  • Follow the steps from Scenario 1 to trigger the email sending
  • The email template should have sections like on this basic email Figma, with addition of Add to cart and purchase section at the top as oi.ie has those events on the website

Scenario 3

  • Following from scenario 2, enable Audience Segmentation on the website
  • Follow the steps from previous scenario to trigger email sending
  • It should have all the sections like in previous email, with addition of New Visitors and Returning Visitors, resembling the full report Figma (Note: Subscribers are just a placeholder, will not be present in real report as such, but custom Audiences will show there when present and have data)

Scenario 4

  • Add another user, with like editor role for example
  • Share SC with the editor
  • Log in as that editor and subscribe to the email repporting
  • Follow the steps from previous scenarios to trigger email sending
  • Verify that user is receiving only SC related data, while admin is receiving full report

Scenario 5

  • Continuing on previous Scenario 4, share GA4 module with the editor
  • trigger email sending like before and verify that user is receiving GA4 related metrics now as well (all shareable data should be present, which should be all the sections, like how admin receives it)

You can experiment with different website that has no purchase/add to cart events, to verify that first section is not showing on such websites

Users with no shared module acces, or that are not subscribed, should not receive an email

Changelog entry

Metadata

Metadata

Labels

P0High priorityPHPTeam SIssues for Squad 1Type: EnhancementImprovement of an existing feature

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions