Premium Analytics: split the Comments widget into Most commented posts and Most commented authors - #50929
Conversation
…oards Breaks the Jetpack Stats "Comments" module out of one widget with an authors/posts view toggle into two focused widgets: - `jpa/most-commented-posts` — posts and pages by comment count. - `jpa/most-commented-authors` — the site's most active commenters. Both read the same all-time `stats/comments` response through a new shared `useStatsCommentsRows` data hook over `selectStatsCommentsRows`, so showing both still costs a single request and the row normalisation lives in the data layer instead of being copied per widget. The Comments report page now reads the same selector. The combined `jpa/comments` widget is removed and the Insights default layout points at the two new widgets. It was never released, so no persisted layout can reference it. WOOA7S-1787
|
Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.
Interested in more tips and information?
|
|
Thank you for your PR! When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:
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:
If you have questions about anything, reach out in #jetpack-developers for guidance! |
Code Coverage SummaryCannot generate coverage summary while tests are failing. 🤐 Please fix the tests, or re-run the Code coverage job if it was something being flaky. |
`toCommentsAuthorRow` and `toCommentsPostRow` derived `label`, `value` and `link` identically; only the row key and the group-specific `avatarUrl` / `postId` differed. Merge them into a single `toCommentsRow( item, group )` that builds the shared fields once and branches only on the genuine differences, carrying both key-derivation rationales into the merged function. The `id` fallback chains are unchanged: authors still key on the gravatar hash then a label-derived key, posts still key on the post id, then the raw link (so identity survives a consumer rejecting that URL), then the label. Adds the fallback-branch tests that were missing first — an author with no gravatar, a post with no id, a post with neither id nor link, and post id 0 (falsy but present, so the check must stay `!= null`). They were written and confirmed green against the two original functions before the merge. WOOA7S-1787
dognose24
left a comment
There was a problem hiding this comment.
Reviewed the diff (tested the sibling PR's flow on a local docker env earlier today). Clean split — one endpoint, two focused leaderboards, and the defaults + PHP test are exactly what I'd hoped to see. Four light notes, nothing blocking:
- Deleting
jpa/commentsoutright is the right call pre-beta (an alias to either new widget would misrepresent the old combined card). One 30-second sanity check worth doing: confirm the host degrades gracefully when a saved layout references a now-unregistered type — a11n dogfooding sites may have persisted boards with the old card, and every future widget removal will lean on the same behavior. An empty slot or dropped entry is fine; a crash isn't. - Cache sharing between the two widgets: since the endpoint returns both groups in one response, please confirm
group(and differingmax) stays out of the query key/request params so both cards share a single cache entry — a small test asserting one request for a board with both widgets would lock it in. - All-time copy: the endpoint is dateless, so both cards show all-time data while sitting under the dashboard's date pills. Worth saying "all-time" in the help copy until the Insights date-model question on WOOA7S-1787 is settled. (Verified the widgets don't consume reportParams, so no stray comparison request here — the stories are the only touchpoints.)
- 👍 for updating
dashboard-layout.phpdefaults with a PHP test in the same PR — #50931 currently leaves its new widget out of the Insights defaults; would be great to mirror this there.

Fixes #
Proposed changes
Splits the Jetpack Stats "Comments" module out of a single widget with an in-widget authors/posts view toggle into two focused, quarter-width Insights widgets, per WOOA7S-1787.
jpa/most-commented-posts— "Most commented posts": the posts and pages that receive the most comments, each row linking to the published post (throughsafeHttpUrl).jpa/most-commented-authors— "Most commented authors": the site's most active commenters, avatar + name, each row linking to the comment management screen filtered to that author when the report carries an email for them.stats/commentsresponse through a newuseStatsCommentsRows( { group, max } )hook over a newselectStatsCommentsRows()selector inpackages/data/src/processing/stats/comments.ts. Row keying, flattening, sorting andmaxtrimming (0= all rows, vialimitStatsRows) live in the data layer; only the label/media/link treatment differs per widget. The Comments report page (routes/reports/comments/config/use-report-records.ts) now reads the same selector instead of carrying its own copy of the mapping.jpa/commentswidget is removed and the Insights default layout points at the two new widgets instead. See "Fate of the old widget" below.<WidgetState>, withdescribeError()so only retryable failures (the proxy'sno_connection403) offer Retry, and a neutral per-widget glyph for empty.Defaultclose-up,Loading/ErrorState/RetryableErrorState/Emptyforced-state stories, and aWidgetDashboardWithWidgetstory mounting the real dashboard. A sharedforceStatsCommentsState()helper was added next toforceWordAdsEarningsState()so the two story files don't each hand-roll the cache reset (thestats/commentsquery key carries no date params, so a distinct preset can't isolate a forced-state story). NoWithComparisonstory:useStatsCommentsis not amergeComparisonRowshook — the endpoint is all-time and has no comparison period.Fate of the old
jpa/commentswidget: removedjpa/commentsis removed rather than kept for back-compat:changelog/add-comments-widget) is still pending andCHANGELOG.mdhas no releases, so no persisted user layout in the wild can referencejpa/comments.jpa/videoswidget the same way — drop the widget, repoint the default layout, add aremovedchangelog entry alongside the originaladdedone.WidgetChromerenders an "Widget is no longer available." card naming the missing type for an unknown widget in a saved layout, so even a stale layout would not crash.viewattribute toggle is exactly what the split removes.Design notes / points a human may want to veto
jpa/most-commented-*slugs so the registered name and the visible title can't drift. Easy to flip back if the issue wording was intended.jpa/tagscurrently sits in Insights row 2 and was left alone, and two prototype modules (All-time total views — WOOA7S-1512, Most popular post — part of WOOA7S-1510) are not ported yet, so the Insights layout still can't match the prototype row-for-row.<ReportLink report="comments" section="posts|authors">footer, as the old Comments widget had — dropping it would remove the only entry point into the Comments report page. Trivial to remove if the design is authoritative here.maxdefault kept at 10. The prototype shows 7 rows; 10 matches the old Comments widget and the neighbouring Insights leaderboards (jpa/shares,jpa/tags). Rows are trimmed after fetching, somax = 0still means "all rows".Related product discussion/links
Does this pull request change what data or activity we track or use?
No. Both widgets read the existing all-time
stats/commentsreport through the existing Premium Analytics data proxy — no new endpoint, no new prefix inPREFIX_CONFIG, no new tracking.Testing instructions
jetpack build --deps packages/premium-analytics(orjetpack build plugins/premium-analytics --deps).http(s)renders as plain text instead of a link.edit-comments.php?s=<email>(the comment management screen filtered to them), while a WordPress.com user row stays unlinked.0shows every row.pnpm storybook:devinprojects/js-packages/storybook):Packages/Premium Analytics/Widgets/MostCommentedPostsand.../MostCommentedAuthors— checkDefault, theWidgetDashboardWithWidgetdashboard story, and theLoading/ErrorState(no Retry) /RetryableErrorState(Retry) /Emptystates.jetpack test js packages/premium-analytics,jetpack test php packages/premium-analytics,jetpack phan packages/premium-analytics.🤖 Generated with Claude Code
https://claude.ai/code/session_01HAX3YkQxDLLXhKXjft6qU2