Show the same Site Goals groups in the email report and on the dashboard
- Dominant language
- JavaScript
- Stars
- 1.4k
- Forks
- 383
- Avg merge
- 4d 14h
- Merged PRs (30d)
- 77
Description
## Feature Description
The Site goals widgets on the dashboard have a tab for each plugin or form.
The Online store widget, with a tab for each plugin
The Lead generation widget, with a tab for each form
The email report shows the same plugins and forms as groups.
The Site Goals cards in the email report
The two build their lists in different ways:
- The dashboard reads the last 90 days, so changing the date range never adds or removes a tab.
- The email reads the report period only, and shows the biggest count first.
So the email and the dashboard can show a different set of forms, in a different order, on the same day.
Make the email read the same 90 days, so both show the same groups.
Two things come with that change. The email asks Analytics for one more report for each breakdown. And a form with no completions in the week shows as a group of zeros.
The email starts showing these cards in #13169.
This is a follow-up to [a review comment on #13426](https://github.com/google/site-kit-wp/pull/13426#discussion_r3870171200), which asked for this ticket.
---------------
_Do not alter or remove anything below. The following sections will be managed by moderators only._
## Acceptance criteria
* Each Site Goals card in the email report shows the same groups as the matching widget on the Site Kit main dashboard:
* The online store card matches the **Online store performance** widget, which shows one tab for each ecommerce plugin.
* The lead generation card matches the **Lead generation performance** widget, which shows one tab for each form.
* A card shows an **Other sources** group only when its widget shows an **Other sources** tab.
* The email builds each card's group list from the 90 days that end on the last day of the report period:
* The group with the most key actions over those 90 days comes first.
* The report period never adds or removes a group, whatever its length.
* Each group's rate and total still cover the report period. Each change badge compares the report period against the previous period.
* A group with no key action in the report period shows a rate of `0%` and a total of `0`:
* When the previous period also has no key action, neither tile shows a change badge.
* When the previous period has key actions, both tiles show a `-100%` change badge.
* A card whose groups all show `0` for the report period is still left out of the email.
* On a site whose Analytics property has no breakdown custom dimension, each Site Goals card is unchanged. The card shows one group and the prompt to **enable data breakdown**.
* The Site Goals widgets on the Site Kit main dashboard are unchanged.
## Implementation Brief
* [ ] Update `includes/Modules/Analytics_4/Email_Reporting/Report_Options.php`
* Following `BREAKDOWN_DISCOVERY_DAYS` https://github.com/google/site-kit-wp/blob/675f77ddfe4dbe16e0c8eb5424caa3a092621971/assets/js/modules/analytics-4/datastore/site-goals-breakdown.ts#L51 in `site-goals-breakdown.ts`, add a constant like `SITE_GOALS_DISCOVERY_DAYS` holding `90`.
* Following `getBreakdownReportOptions` https://github.com/google/site-kit-wp/blob/675f77ddfe4dbe16e0c8eb5424caa3a092621971/assets/js/modules/analytics-4/datastore/site-goals-breakdown.ts#L142-L173 in `site-goals-breakdown.ts`, add a method like `with_discovery_range` that holds a discovery report to the same days, whatever the report period's length:
* Take the report options array as its argument.
* Set `endDate` to the report period's end date from `get_current_range_values()`, and `startDate` to `SITE_GOALS_DISCOVERY_DAYS` days before it.
* Order the rows by the biggest `eventCount` first, with `'orderby' => array( array( 'metric' => array( 'metricName' => 'eventCount' ), 'desc' => true ) )`.
* Add two methods like `get_online_store_discovery_options` and `get_lead_discovery_options` that name the groups each Site Goals card shows:
* Take the card's breakdown custom dimension slug as its argument.
* Build the options with `build_event_count_options()`, and return them through `with_discovery_range()`.
* Following the `useSiteGoalsBreakdown` https://github.com/google/site-kit-wp/blob/675f77ddfe4dbe16e0c8eb5424caa3a092621971/assets/js/modules/analytics-4/components/site-goals/widgets/OnlineStorePerformanceWidget.tsx#L320-L326 call in the Online store performance widget, filter `eventName` with an `inListFilter`:
* `get_online_store_discovery_options()` takes both ecommerce event names, `Conversion_Reporting_Events_Sync::ECOMMERCE_EVENT_NAMES`.
* `get_lead_discovery_options()` takes the events `get_detected_lead_events()` returns.
* Move the `with_current_range( $options, true )` call out of `build_event_count_options()` into `get_online_store_primary_options()` and `get_lead_primary_options()`.
* [ ] Update `includes/Modules/Analytics_4/Email_Reporting/Report_Request_Assembler.php`
* Add two payload keys like `SITE_GOALS_ONLINE_STORE_DISCOVERY_KEY` holding `'site_goals_online_store_discovery'` and `SITE_GOALS_LEAD_DISCOVERY_KEY` holding `'site_goals_lead_discovery'`.
* List both keys in `SITE_GOALS_REQUEST_KEYS`.
* In `build_site_goals_requests()`, register a discovery report inside each `has_custom_dimension_data()` block:
* `SITE_GOALS_ONLINE_STORE_DISCOVERY_KEY` takes `get_online_store_discovery_options( Analytics_4::CUSTOM_DIMENSION_EVENT_PROVIDER )`.
* `SITE_GOALS_LEAD_DISCOVERY_KEY` takes `get_lead_discovery_options( Analytics_4::CUSTOM_DIMENSION_FORM_ID )`.
* [ ] Update `includes/Modules/Analytics_4/Email_Reporting/Site_Goals_Section_Builder.php`
* In `build_online_store_section()` and `build_lead_generation_section()`, read the card's discovery report through `extract_report_rows()`, into a variable like `$discovery_rows`.
* In both methods, pass `sum_metric_by_group( $discovery_rows, $group_dimension, 'eventCount' )` to `get_provider_group_labels()` and `get_form_group_labels()`, in place of the report period counts.
* Add a method like `has_other_sources` that decides the "Other sources" group from the days the discovery report covers. This replaces the two-report subtraction `hasUnattributedEvents` https://github.com/google/site-kit-wp/blob/675f77ddfe4dbe16e0c8eb5424caa3a092621971/assets/js/modules/analytics-4/datastore/site-goals-breakdown.ts#L890-L940 runs on the dashboard, rather than reproducing it:
* Take the discovery rows, the group dimension, and the group names the card shows a group for.
* Return whether a group outside those names counted an event.
* The discovery report already returns a row per dimension value, so the count needs no report of its own. GA4 returns `(not set)` for an event that never set the dimension, and `(other)` once the report passes its cardinality limit; neither becomes a named group, so both fall to "Other sources" the same way the dashboard's subtraction puts them there.
* Set a `shows_other_sources` key in each card's `$section_input` array from `has_other_sources()`:
* `build_online_store_section()` passes the discovery rows whose `eventName` holds the event `find_primary_event()` found.
* `build_lead_generation_section()` passes every discovery row.
* In `build_section()`, build the "Other sources" group when `shows_other_sources` reads true, in place of the `sum_other_sources_counts()` total test.
### Test Coverage
* Extend `tests/phpunit/integration/Modules/Analytics_4/Email_Reporting/Report_OptionsTest.php` to cover the two discovery reports:
* Each card counts its own key actions: both ecommerce events for the online store, and every detected lead event for lead generation.
* Each card names its groups from the 90 days that end on the report period's last day, whatever that period's length.
* The previous period adds no group to either card.
* The group with the most key actions in those 90 days comes first.
* Extend `tests/phpunit/integration/Modules/Analytics_4/Email_Reporting/Report_Request_AssemblerTest.php` to cover the two payload keys:
* A card asks Analytics for one more report only where its breakdown custom dimension holds data.
* `SITE_GOALS_REQUEST_KEYS` lists every payload key `build_requests()` registers, including the two new ones.
* Extend `tests/phpunit/integration/Modules/Analytics_4/Email_Reporting/Site_Goals_Section_BuilderTest.php` with a discovery report in every fixture that splits its results:
* Each card's groups, and their order, come from the 90 days rather than from the report period.
* A card shows "Other sources" only where the 90 days hold a key action outside the groups the card names.
* Every group's rate and total count the report period, so a group with no key action shows `0%` and `0`.
* A `-100%` change badge shows only where the previous period held key actions.
* A card whose report period holds no key action stays out of the email, even where the 90 days name a group.
## QA Brief
- **Note:** The Site Goals cards are not rendered in the email yet - that lands in #13169. This issue only changes which groups the data produces and in what order, so the visual comparison against the dashboard is QA-able once #13169 is in.
**Setup**
- Analytics connected, and the site sends at least one ecommerce event (`purchase` / `add_to_cart`) and one lead event (`submit_lead_form` / `contact` / `generate_lead`). With breakdown data enabled
**Testable now**
- Send a weekly report. It still arrives, and the email log ends as `email_sent` with no error details. This change adds two report requests per email, so an `email_report_batch_incomplete` error would be a regression from this issue.
- A site with no breakdown dimension is also unchanged - one group, plus the "enable data breakdown" prompt.
## Changelog entry
- Show Site Goals groups consistently between email reports and dashboard.
Contributor guide
Research direction
Start with the implementation brief and read includes/Modules/Analytics_4/Email_Reporting/Report_Options.php, Report_Request_Assembler.php, and Site_Goals_Section_Builder.php, then run the corresponding Report_OptionsTest.php, Report_Request_AssemblerTest.php, and Site_Goals_Section_BuilderTest.php. Add the two 90-day discovery reports and ensure group names and Other sources match the dashboard while period totals, rates, and change badges remain correct.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, php
- Domain
- analytics, backend, testing-qa
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 72/100