Skip to content

Premium Analytics: add Size to the Top platforms "View by" control - #51270

Closed
kangzj wants to merge 7 commits into
trunkfrom
echo/wooa7s-1940-top-platforms-size
Closed

kangzj wants to merge 7 commits into
trunkfrom
echo/wooa7s-1940-top-platforms-size

Conversation

@kangzj

@kangzj kangzj commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

Follows WOOA7S-1940 (the second half of that report)

Why

WOOA7S-1940 said the Top platforms widget was "missing platform distribution". It was: the widget offered Browser and OS, which is two of the three breakdowns stats/devices/{property} actually serves. The screen-size split — Desktop / Mobile / Tablet — was unreachable from it. This adds it as Size.

Proposed changes

  • Add Size to the Top platforms "View by" control. The options are now Browser, OS, Size.
  • Format Size as a percentage. WordPress.com special-cases screensize and returns percentage shares, while browser and platform return view counts, so the leaderboard prints the two units accordingly. Bar widths stay relative to the largest visible value either way.
  • Guard the persisted platformDimension against a value outside the supported set, so a stale layout can't turn into a stats/devices/<unknown> request.
  • Drop client_type from StatsDeviceProperty. It is not one of the properties the endpoint accepts, so a request naming it is rejected before any query runs. Nothing called it; the Storybook mock that pretended it worked is gone too.

Browser stays the first option deliberately: the shared SelectField displays the first element when the attribute is unset, so the first option has to match the render default. If the design wants Size first, the render default and the example attributes should move with it — say the word and I'll flip both together.

Screenshots

Size selected — Desktop / Mobile / Tablet as shares of all views:

Top platforms widget in Size mode

Related product discussion/links

Does this pull request change what data or activity we track or use?

No. Size reads stats/devices/screensize, the same endpoint and property the existing Devices widget already requests.

Testing instructions

  • Go to Jetpack → Stats → Traffic on a Jetpack-connected site with traffic.
  • Open the Top platforms widget's "View by" dropdown — it lists Browser, OS, Size. Before this change only Browser and OS were there.
  • Select Size. Rows read Desktop / Mobile / Tablet with percentages (e.g. 57.8%), not view counts.
  • Switch back to Browser and OS — both still list view counts, unchanged.
  • Add a fresh Top platforms widget to the dashboard. The control reads Browser and the rows are browsers — the label and the data agree.

Storybook covers the same states without a WordPress install: Packages/Premium Analytics/Widgets/TopPlatforms now has a BySize story alongside Default and ByOS.

Note on the screenshot

The dashboard site used for the screenshot is in offline mode, so its stats/devices/* responses were mocked locally with the shapes WordPress.com actually returns (percentage shares for screensize, counts for the other two). The endpoint's property set and response shapes were confirmed against the WordPress.com server code rather than assumed.

Jasper Kang added 4 commits August 14, 2026 15:52
The widget exposed two of the three properties stats/devices/{property}
serves — browser and platform — so the screen-size breakdown was unreachable
from it.

Size needs its own formatting: WPCOM special-cases screensize and returns
percentage shares, while browser and platform return view counts. The
leaderboard prints the two units accordingly; bar widths stay relative to the
largest visible value either way.

Also drop client_type from StatsDeviceProperty. It is not one of the three
properties the endpoint accepts, so a request naming it is rejected with a 400
before any query runs. Nothing called it.
widget.json is the registered widget's catalog and help copy, and it still
described only browsers and operating systems.
SelectField renders the first element when the attribute is unset, so listing
Size first made an unconfigured widget label itself "Size" while still
fetching browser data. Size moves to the end, matching the render default, and
a test pins the first element to the default so the two cannot drift.
@kangzj kangzj added Enhancement Changes to an existing feature — removing, adding, or changing parts of it [Status] In Progress labels Aug 14, 2026
@kangzj kangzj self-assigned this Aug 14, 2026
@kangzj

This comment has been minimized.

@kangzj

This comment has been minimized.

@github-actions

github-actions Bot commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack or WordPress.com Site Helper), and enable the echo/wooa7s-1940-top-platforms-size branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack echo/wooa7s-1940-top-platforms-size
bin/jetpack-downloader test jetpack-mu-wpcom-plugin echo/wooa7s-1940-top-platforms-size

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@claude

This comment has been minimized.

@github-actions

github-actions Bot commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!


Premium Analytics plugin:

No scheduled milestone found for this plugin.

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.

This comment has been minimized.

@jp-launch-control

jp-launch-control Bot commented Aug 14, 2026 •

Copy link
Copy Markdown

Code Coverage Summary

Coverage changed in 5 files.

File Coverage Δ% Δ Uncovered
projects/packages/premium-analytics/packages/data/src/hooks/use-stats-devices.ts 2/2 (100.00%) 50.00% -1 💚
projects/packages/premium-analytics/widgets/devices/use-device-views.ts 0/7 (0.00%) 0.00% -1 💚
projects/packages/premium-analytics/packages/widgets-toolkit/src/helpers/format-display-label.ts 4/4 (100.00%) 100.00% -2 💚
projects/packages/premium-analytics/widgets/top-platforms/use-platform-views.ts 12/12 (100.00%) 100.00% -10 💚
projects/packages/premium-analytics/widgets/top-platforms/render.tsx 16/17 (94.12%) 94.12% -12 💚

1 file is newly checked for coverage.

File Coverage
projects/packages/premium-analytics/packages/widgets-toolkit/src/helpers/device-labels.ts 1/1 (100.00%) 💚

Full summary · PHP report · JS report

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Size (screensize) as a third “View by” dimension for the Premium Analytics Top platforms widget, including correct formatting for the endpoint’s mixed units (counts vs percentage shares), and tightens the allowed device-property set in the data layer.

Changes:

  • Add Size as a selectable dimension and render it as percent shares while keeping Browser/OS as counts.
  • Guard persisted platformDimension values to prevent unsupported stats/devices/{property} requests.
  • Remove unsupported client_type from StatsDeviceProperty, and update Storybook mocks + add widget unit tests.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
projects/packages/premium-analytics/widgets/top-platforms/widget.ts Adds screensize to widget attributes and to the “View by” control options.
projects/packages/premium-analytics/widgets/top-platforms/widget.json Updates widget description/help text to reflect Size support and mixed units.
projects/packages/premium-analytics/widgets/top-platforms/use-platform-views.ts Adds screensize label mapping and supports screensize as a device property.
projects/packages/premium-analytics/widgets/top-platforms/stories/top-platforms-widget.stories.tsx Expands Storybook controls and adds a BySize story.
projects/packages/premium-analytics/widgets/top-platforms/render.tsx Formats screensize rows as percentages, keeps bars relative, and guards persisted dimensions.
projects/packages/premium-analytics/widgets/top-platforms/tests/top-platforms.test.tsx Adds tests for requested device property, default behavior, invalid persisted values, and formatting.
projects/packages/premium-analytics/packages/widgets-toolkit/src/stories/mocks/register-stats-mocks.ts Removes the invalid client_type devices mock branch; keeps platform-only routing.
projects/packages/premium-analytics/packages/data/src/queries/stats-devices-query.ts Narrows StatsDeviceProperty to the endpoint-supported set.
projects/packages/premium-analytics/changelog/add-wooa7s-1940-top-platforms-size Adds a package changelog entry for the new Size breakdown.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Significance: minor
Type: added

Top platforms: offer Size alongside Browser and OS in the widget's "View by" control.
Comment on lines +10 to +13
import type { ReportParams, StatsDevicesComparisonItem } from '@jetpack-premium-analytics/data';

export type PlatformDimension = 'screensize' | 'browser' | 'platform';

- PlatformDimension aliases StatsDeviceProperty instead of restating it, so the
  label map stays exhaustive when the endpoint's property set changes.
- Hoist the screen-size labels into widgets-toolkit; Devices and Top platforms
  were translating the same six strings separately.
- Derive the supported-dimension guard from that label map rather than keeping a
  second copy of the list.
- Cover the guard directly, drop the it.each row that duplicated the defaults
  test, and add a Size-with-comparison story for the one Size state nothing
  exercised.
- Correct a docblock that still described two dimensions.
- Add the plugins/premium-analytics changelog entry the package-only entry
  should have been paired with.
@kangzj

This comment has been minimized.

@kangzj

This comment has been minimized.

@kangzj

This comment has been minimized.

@claude

This comment has been minimized.

This comment has been minimized.

- The attribute type was the one place still restating the endpoint's property
  set; it aliases StatsDeviceProperty like the hook does, so the guard and the
  attribute type cannot diverge.
- Cover the per-dimension label mapping, which the render tests could not reach
  because they stub the hook wholesale.
- formatDisplayLabel looked up plain-object keys unguarded, so a key named
  toString returned an inherited function where a string was expected. No API
  vocabulary triggers it, but this change points a second widget at that lookup.
@kangzj

This comment has been minimized.

@kangzj

This comment has been minimized.

@claude

This comment has been minimized.

A failing assertion would have skipped the restore on the line below it and
leaked the override into whatever test was appended next. The override is local
to the mock now, and the fixture map is readonly so it cannot drift back.
@kangzj

This comment has been minimized.

@kangzj

kangzj commented Aug 14, 2026

Copy link
Copy Markdown
Contributor Author

Review-cycle summary — 281043087f → 3f17a5d1f6

3 rounds; CI green (62 passing, 0 failing); 12 findings triaged, 10 applied and 2 declined with reasons.

What changed during the cycle

Commits added:

  • 3f17a5d1f6 — Address review: stop the fallback test mutating a shared fixture
  • 63779e2402 — Address review: close the last union copy and the label-map lookup hole
  • d58012b7cf — Address review: share the device vocabulary and the dimension list

Diff summary: 14 files changed, 202 insertions(+), 60 deletions(-)

Findings addressed:

Round Source Finding Resolution
1 claude PlatformDimension was a third copy of StatsDeviceProperty Aliased the shared type, so the exhaustive label map breaks the build on an upstream change — d58012b7cf
1 claude Screen-size labels duplicated the Devices widget's map Hoisted to widgets-toolkit/helpers/device-labels.ts; both widgets import it — d58012b7cf
1 claude SUPPORTED_DIMENSIONS was a fourth copy of the list Replaced with isPlatformDimension() keyed off the label map — d58012b7cf
1 claude Test nits; hook had no coverage Dropped the duplicated it.each row; the render mock now spreads requireActual so the guard test exercises shipped code — d58012b7cf
1 claude Stale docblock Updated — d58012b7cf
1 claude Missing plugin changelog entry Added plugins/premium-analytics — d58012b7cf
1 copilot sharePercentage receives the raw value; comment placement Documented why the raw value is deliberate and moved the conversion comment — d58012b7cf
2 claude widget.ts was the last hand-written copy of the union Aliased StatsDeviceProperty — 63779e2402
2 claude toPlatformView uncovered Hook-level tests through the real query path, one key per dimension plus the title-case fallback — 63779e2402
2 claude Drive-by: formatDisplayLabel prototype hole Own-property lookup plus tests. Taken rather than deferred: this PR points a second widget at that helper — 63779e2402
3 claude Fallback test mutated a shared fixture without a finally Override is local to the mock; fixture map is Readonly — 3f17a5d1f6

Declined:

  • plugins/jetpack changelog entry. The dashboard is behind Jetpack::is_premium_analytics_enabled() (class.jetpack.php:871-889), which defaults to false, so it isn't reachable by Jetpack users yet. wpcomsh and mu-wpcom-plugin are sticker-gated similarly. Per the rule's own "not to every dependent by reflex".
  • Folding build-sessions-by-device-data.ts's Desktop/Mobile/Tablet map into SCREEN_SIZE_LABELS. It maps device_type from the report layer rather than stats/devices/screensize, so merging them would assert an unverified equivalence between two API vocabularies. Flagged for a follow-up instead.

Design question surfaced, not silently decided: calculateDelta on Size compares two shares, so 57.8% vs 52.3% renders as +10.5% while the share moved +5.5 points. Reachable with comparison on. A BySizeWithComparison story now puts that state in front of a reviewer.

Verification: 18 top-platforms tests across 3 suites, 5 for formatDisplayLabel, full package suite at 2041 passing (the single failure, packages/routing/.../build-range-patch.test.ts, is pre-existing on trunk), typecheck and ESLint clean. All three dimensions re-exercised in a live dashboard after each rebuild — the final pass against the site's real Stats data with no local mock.

@kangzj kangzj added [Status] Needs Team Review Obsolete. Use Needs Review instead. and removed [Status] In Progress labels Aug 14, 2026
@kangzj
kangzj marked this pull request as ready for review August 14, 2026 05:34
@kangzj
kangzj requested a review from a team as a code owner August 14, 2026 05:34

@dognose24 dognose24 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! The unit-conversion chain is careful (display values converted, bar widths and calculateDelta deliberately on raw values — scale-invariant either way), the stale-attribute guard matches the SelectField first-element convention with a test that reads the definition directly, and the client_type removal is clean — I grepped both premium-analytics projects and found no remaining references.

One non-blocking product question to settle before or after merge: in Size + comparison mode, a share moving from 52.3% to 57.8% currently shows the relative change (+10.5%) rather than +5.5 pp. Two percentages with different meanings sit side by side on the same row — the BySizeWithComparison story you added shows it well. If design is happy with relative change, the implementation is already correct; just flagging so it's a decision rather than an accident.

Also left one tiny i18n suggestion inline.

value: 'platform',
},
{
label: __( 'Size', 'jetpack-premium-analytics-pkg' ),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Size is an isolated string for translators and easily lands as "file size" / "dimensions" in some locales. A translator context would pin it down:

Suggested change
label: __( 'Size', 'jetpack-premium-analytics-pkg' ),
label: _x( 'Size', 'Screen size breakdown: Desktop / Mobile / Tablet', 'jetpack-premium-analytics-pkg' ),

(with _x added to the @wordpress/i18n import). Browser/OS are less ambiguous, fine as they are.

@dognose24

dognose24 commented Aug 14, 2026 •

Copy link
Copy Markdown
Contributor

Thanks for digging into the server side! One thing I want to double-check before this lands: the screen-size split already has its own widget on the same Traffic page — Devices (row 2) renders stats/devices/screensize as the Desktop / Mobile / Tablet semi-circle — and the design mock I have shows Top platforms' "View by" offering exactly Browsers / OS, with Size deliberately split out to Devices (screenshot below).

截圖 2026-08-14 下午2 18 54

Is this addition based on an updated design or product direction I might have missed? If design does want Size inside Top platforms too, great — but if not, we'd be duplicating the Devices card two rows below it and diverging from the mock. Your first comment on WOOA7S-1940 read it the same way (a product decision worth its own issue), so I figured it's worth confirming which direction is current before merging.

@kangzj

kangzj commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @dognose24! I didn't realized it's split into two widgets. Closing...

@kangzj kangzj closed this Aug 17, 2026
@github-actions github-actions Bot removed [Status] In Progress [Status] Needs Team Review Obsolete. Use Needs Review instead. labels Aug 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement Changes to an existing feature — removing, adding, or changing parts of it [Package] Premium Analytics [Plugin] Premium Analytics

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants