Add the Site Goals Key Metric tiles for the Selling products group
- Dominant language
- JavaScript
- Stars
- 1.4k
- Forks
- 383
- Avg merge
- 4d 12h
- Merged PRs (30d)
- 80
Description
## Feature Description
The Site Goals widget is only rendered when a supported Event Provider plugin is active, because its tabbed breakdown depends on the custom dimension data (event provider source and form ID) that Site Kit itself appends as part of Plugin Conversion Reporting. When the events are detected but tracked by another plugin, Site Kit cannot append that data, so the Site Goals widget is not shown at all.
Aggregated data for those same key actions is still useful in that situation, so we are building it out as Key Metric Widget tiles instead. This issue covers the eight new tiles in the `Selling products` group. The `Generating leads` group is covered in #13421, and renaming the existing ACR tiles in both groups in #13414.
This issue also introduces the shared reporting module both of the other two depend on.
Detection logic is unchanged — the tiles are still driven by the same five events Site Kit already detects and tracks: `purchase`, `add_to_cart`, `submit_lead_form`, `contact` and `generate_lead`.
Figma mock: [Site Goals — Key Metric tiles](https://www.figma.com/design/S2CNc1toIzC7UrGMgs79S6/Site-Goals?node-id=7385-80843&m=dev)
---------------
_Do not alter or remove anything below. The following sections will be managed by moderators only._
## Acceptance criteria
When the `purchase` event has been detected, the Key Metrics selection panel offers these new tiles in the `Selling products` group.
* Single-value tiles, each showing the change vs. the previous period:
* `Total sales` — the count of `purchase` events for the selected date range
* `Sales rate` — a percentage, subtitled with the total session count
* `Sales engagement rate` — a percentage, subtitled with the total session count
* List tiles, each showing the top three rows for the selected date range with each row's share of the total as a percentage:
* `Top traffic channels by sales rate`
* `Sales by visitor type`
* `Sales by countries`
* `Top authors driving sales` — only offered when the `googlesitekit_post_author` custom dimension is available, as the existing `Most popular authors by pageviews` tile is
* `Top pages driving sales` — a list tile as above, but each row shows a raw event count
* Titles match the [Figma mock](https://www.figma.com/design/S2CNc1toIzC7UrGMgs79S6/Site-Goals?node-id=7385-80843&m=dev).
* Each tile's selection panel description and its info tooltip are the same string, taken from the `Metric description in panel/info icon` column of the [KMW metrics list](https://docs.google.com/spreadsheets/d/1Cf3GWk33CYm0AS_d3TbkGeluELBkAM-V26xcETpAUUg/edit?usp=sharing).
* `Sales rate` and `Sales engagement rate` end in a `Learn more` link, pointing at `site-goals-online-store-key-action` and `site-goals-engagement-rate` — the targets the Site Goals widget already uses.
* Row values match the equivalent Site Goals widget tile.
* Tiles appear whenever `purchase` is detected, regardless of whether the Site Goals widget is rendered.
* The group keeps its existing ACR tiles not listed above
* The Site Goals widget is unchanged for the user, despite its reporting logic moving to a shared module.
## Implementation Brief
* [ ] Add `assets/js/modules/analytics-4/components/site-goals/goal-drivers/reports.ts`
* Lift the `reportOptions` builder and the row mapper out of each component in `assets/js/modules/analytics-4/components/site-goals/goal-drivers/`, keyed by `GOAL_DRIVER_IDS`
* Each builder takes the date range, `primaryEvent`, an optional `breakdownFilter` and a row limit, and returns report options - the builders stay goal-type agnostic so the sibling leads issue reuses them unchanged
* Each mapper takes report rows and returns `GoalDriverRow[]` - share of total as a percentage for every driver except `TOP_PAGES`, which returns `numFmt( eventCount )`, as in `CitiesGoalDriver` https://github.com/google/site-kit-wp/blob/582d0b40a871906c6cba34c969ca4cf65a47b5c1/assets/js/modules/analytics-4/components/site-goals/goal-drivers/CitiesGoalDriver.tsx#L137-L156
* _The percentage denominator is summed from the returned rows, so the requested limit changes the value. Use one limit for both surfaces._
* Add builders for the three ecommerce headline metrics, lifted from `OnlineStorePerformanceWidget` and `EngagementRateTile`
* [ ] Update each goal driver component in `assets/js/modules/analytics-4/components/site-goals/goal-drivers/`
* Replace the inline `reportOptions` `useMemo` and the row mapping with the builder and mapper from `reports.ts`
* [ ] Update `assets/js/googlesitekit/datastore/user/constants.js`
* Add a `KM_ANALYTICS_*` constant per tile in the ACs, following the existing `kmAnalytics*` value convention
* Add each to `keyMetricsGA4Widgets` https://github.com/google/site-kit-wp/blob/582d0b40a871906c6cba34c969ca4cf65a47b5c1/assets/js/googlesitekit/datastore/user/constants.js#L98
* _`KM_ANALYTICS_TOP_CATEGORIES` is listed twice in this array today. Deduplicate it while here rather than adding to the pattern._
* [ ] Update `assets/js/components/KeyMetrics/key-metrics-widgets.js`
* Add a `KEY_METRICS_WIDGETS` entry per new slug with `title`, `description` and `infoTooltip` from the ACs
* Set `metadata.group` to `KEY_METRICS_GROUP_SELLING_PRODUCTS.SLUG`
* Set `requiredConversionEventName` to `[ ENUM_CONVERSION_EVENTS.PURCHASE ]` and use `shouldDisplayWidgetWithConversionEvent` for `displayInSelectionPanel` and `displayInList`, as the existing ACR entries do
* For `Top authors driving sales` also set `requiredCustomDimensions` to `[ 'googlesitekit_post_author' ]` and use `shouldDisplayWidgetWithCustomDimensions`, as `KM_ANALYTICS_POPULAR_AUTHORS` https://github.com/google/site-kit-wp/blob/582d0b40a871906c6cba34c969ca4cf65a47b5c1/assets/js/components/KeyMetrics/key-metrics-widgets.js#L192-L206 does
* Add a documentation slug field on the two entries whose copy ends in `Learn more`, using the slugs in the ACs
* [ ] Update `assets/js/components/KeyMetrics/MetricTileHeader.js`
* When the catalogue entry carries a documentation slug, render the trailing `Learn more` as a link resolved through the `getDocumentationLinkURL` selector on `CORE_SITE`
* [ ] Add a widget component per tile in `assets/js/modules/analytics-4/components/widgets/`
* Use `MetricTileNumeric` for `Total sales`, `Sales rate` and `Sales engagement rate`, passing the value, `subText` and `currentValue`/`previousValue`
* Use `MetricTileTable` for the other five, following the `columns` shape in `TopCitiesDrivingPurchasesWidget` https://github.com/google/site-kit-wp/blob/582d0b40a871906c6cba34c969ca4cf65a47b5c1/assets/js/modules/analytics-4/components/widgets/TopCitiesDrivingPurchasesWidget.js#L126-L147
* Take report options and rows from `assets/js/modules/analytics-4/components/site-goals/goal-drivers/reports.ts`
* [ ] Update `assets/js/modules/analytics-4/widgets/index.js`
* Register each new slug in `AREA_MAIN_DASHBOARD_KEY_METRICS_PRIMARY` with `WIDGET_WIDTHS.QUARTER`, `wrapWidget: false`, `modules: [ MODULE_SLUG_ANALYTICS_4 ]` and an `isKeyMetricActive` guard, as the ACR tiles are registered https://github.com/google/site-kit-wp/blob/582d0b40a871906c6cba34c969ca4cf65a47b5c1/assets/js/modules/analytics-4/widgets/index.js#L788-L802
* _Consider driving the registration from a table keyed by slug - the blocks differ only by slug and component, and the sibling leads issue adds eight more._
* [ ] Update `assets/js/modules/analytics-4/datastore/conversion-reporting.js`
* Add the new slugs to the `purchase` array returned by `getKeyMetricsConversionEventWidgets` https://github.com/google/site-kit-wp/blob/582d0b40a871906c6cba34c969ca4cf65a47b5c1/assets/js/modules/analytics-4/datastore/conversion-reporting.js#L352-L372
* [ ] Update `assets/js/components/KeyMetrics/key-metrics-pdf-tiles.js`
* Add an entry per new slug mirroring the on-screen layout and value formatting
### Test Coverage
* Add unit tests for the builders and mappers in `reports.ts`, and update the existing goal driver tests to exercise them through it, so the Site Goals widget is proven unchanged by the extraction
* Update `assets/js/components/KeyMetrics/key-metrics-widgets.test.js` and `assets/js/modules/analytics-4/datastore/conversion-reporting.test.js` to cover the new slugs — offered only when `purchase` is detected, and `Top authors driving sales` additionally requiring `googlesitekit_post_author`
* Add a test file per new widget component following `TopCitiesDrivingPurchasesWidget.test.js` — loading, error, zero-data and populated states, asserting row value formatting explicitly
* Add coverage for the `Learn more` tooltip link, including that tiles without a documentation slug render an unchanged plain-text tooltip
* Add a Storybook story per new tile, matching the existing ACR tile stories
## QA Brief
* With `purchase` detected as a conversion event, open the Key Metrics selection panel → Selling products tab and confirm all 8 new tiles are offered (Total sales, Sales rate, Sales engagement rate, Top traffic channels by sales rate, Sales by visitor type, Sales by countries, Top authors driving sales, Top pages driving sales), alongside the group's existing tiles.
* Select and apply all 8; confirm each renders on the dashboard: `Total sales` / `Sales rate` / `Sales engagement rate` as a single value with a change badge vs. the previous period, and the remaining four as a 3-row list with each row's share of the total as a percentage — except `Top pages driving sales`, which shows a raw event count per row.
* Hover the info icon on `Sales rate` and `Sales engagement rate`; confirm a working `Learn more` link. Confirm the other 6 tiles show a plain-text tooltip with no link, and that every tile's tooltip text matches its panel description.
* With `purchase` not detected, confirm none of the 8 tiles are offered in the selection panel.
* On an admin dashboard without the `googlesitekit_post_author` custom dimension, confirm `Top authors driving sales` shows the "Update Analytics to track metric" CTA, and that clicking it creates the dimension and moves the tile to a gathering-data state.
* On a view-only (shared) dashboard, confirm `Top authors driving sales` is only offered when `googlesitekit_post_author` is available, even if `purchase` is detected.
* Where the Site Goals widget is also visible, compare row values for `Top traffic channels by sales rate`, `Sales by visitor type`, `Sales by countries`, and `Top authors driving sales` against their equivalent Site Goals tile and confirm they match.
* Export the dashboard to PDF and confirm all 8 new tiles appear with the same layout and values as on-screen.
## Changelog entry
* Add Site Goals key metric tiles for "Selling products"
Contributor guide
Research direction
Start with the existing ACR registrations in assets/js/modules/analytics-4/widgets/index.js, TopCitiesDrivingPurchasesWidget and its test, then trace the goal-driver components. Extract and test the shared builders in reports.ts before updating the catalogue, widgets, conversion reporting and PDF tile files. Done means all eight purchase-gated tiles, stories and tests work, including matching Site Goals values and the two Learn more links.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, typescript
- Domain
- analytics, frontend, testing
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 52/100