Skip to content

Premium Analytics: add a per-section all-time and yearly date selection - #50930

Merged
louwie17 merged 6 commits into
trunkfrom
wooa7s-1787-adapt-insights-tab-based-on-current-experience-date-selection
Aug 5, 2026
Merged

louwie17 merged 6 commits into
trunkfrom
wooa7s-1787-adapt-insights-tab-based-on-current-experience-date-selection

Conversation

@louwie17

@louwie17 louwie17 commented Jul 30, 2026 •

Copy link
Copy Markdown
Contributor

Fixes WOOA7S-1787 (partially — the date-selection slice)

Proposed changes

  • Makes the dashboard's date-filter surface a per-section configuration, defaulting to today's rolling date-range picker, and turns the year surface on for Insights.
  • Adds a date_filter section arg to Dashboard_Section — range (the default) or year — parsed alongside label/order/default_layout, exposed in the sections REST response, and documented in a new schema for that route. An unrecognized value falls back to range.
  • Registers analytics/insights with date_filter => year. Every other section is unchanged.
  • Mirrors the field on the frontend (DashboardSection.date_filter) and renders DateYearFilter for year sections, DateFiltersPanel for everything else, through the section header's controls slot.
  • Fills in the SectionHeader subtitle — the slot Premium Analytics: add a per-section header with title and date controls #50894 left with a TODO — with the resolved selection ("All time", "2024") on the year surface.

This builds on #50754, which shipped the all-time / year-<YYYY> presets and the DateYearFilter component but deliberately did not mount them. This PR is that mounting, made configurable per section.

Screenshot 2026-07-31 at 10 59 08

Cross-surface presets

?preset= is one search param shared by every section, so a section switch can land a preset the visible control cannot represent. Rather than leave the filter looking unset, the surface the user is now looking at takes over:

Situation Result
Rolling window / custom / no preset → a year section Becomes all-time
all-time or year-2024 → a range section Becomes the default preset (last-30-days)
Preset the surface can represent (incl. a custom range on range) Left alone

The correction is a replace, not a push, so Back does not return to the state that triggered it and get corrected straight back out of. ?preset=year-2024 still survives a reload untouched while you stay on Insights — that round-trip is what #50754 widened PrimaryPresetId for, and needsReportDateParamsSeed already treats year-surface presets as range-based.

startYear

Left unset, so getYearSurfacePresets falls back to DEFAULT_YEAR_SURFACE_COUNT (6 years — the window the design shows). Nothing in this package knows how far back a site's data goes: getStoreInfo() is still a stub and there is no cheap first-post/site-created source that works on both connected and Simple sites. Rather than build new data plumbing here, this is left as a follow-up — a younger site currently offers years it has nothing to show for.

Custom periods and comparison — open question

Not implemented, per the issue's "should we?" framing. Current behaviour on a year section, for the team to decide on:

  • Custom periods: unavailable. DateYearFilter offers only all time and single years, and a custom preset arriving from another section is replaced with all-time.
  • Comparison: the control is hidden (it lives in DateFiltersPanel), but the comp / compare_* params pass through and stay live. They are not stale: buildRangePatch re-derives the comparison window against each new primary range, so previous-period on year 2024 resolves to 2023. The effect is a coherent "2024 vs 2023" that the user cannot turn off without going back to another section. If that is not wanted, the fix is to clear comparison when moving onto the year surface — deliberately left out of this PR.

REST response shape

Yes, the sections response changed: each section now carries a date_filter key, and the route gained a schema callback. It is a purely additive field with a range default, so existing consumers keep working — but flagging it because WPCOM's public-api calls Dashboard_Support_Routes::register() by name from the wpcom repo (wp-content/rest-api-plugins/jetpack-endpoints/premium-analytics-dashboard.php), per AGENTS.md and #50266. No signature change, so no WPCOM-side update should be required; a WPCOM-side change would only be needed if something there asserts on the exact response shape.

Related product discussion/links

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

No.

Testing instructions

  • Build the package: jetpack build packages/premium-analytics --deps
  • Go to Jetpack → Stats (the Premium Analytics dashboard).
  • Insights tab: the header shows All time | 2026 | 2025 | 2024 | 2023 | 2022 | 2021 pills instead of the date-range picker, with the selection named as a subtitle under the title. There is no comparison dropdown.
  • Click a year — the widgets refetch for that year and the URL gains ?preset=year-2024&from=…&to=…. Reload: the same year stays selected.
  • Traffic / Subscribers / Store: unchanged — the rolling date-range picker plus the comparison dropdown, no subtitle.
  • Cross-surface: from Insights on 2024, switch to Traffic — the picker reads "Last 30 days" rather than a custom range. From Traffic on "Last 7 days", switch to Insights — "All time" is selected rather than every pill unpressed. In both directions, Back goes to the previous section, not into a correction loop.
  • Narrow window: shrink the browser until the pills no longer fit — they collapse to a select.
  • REST: GET /wpcom/v2/dashboards/<name>/sections returns date_filter on every section (year for insights, range for the rest); OPTIONS on the same route returns the new schema.

@louwie17
louwie17 requested a review from a team July 30, 2026 14:45
@louwie17
louwie17 requested a review from a team as a code owner July 30, 2026 14:45
@louwie17 louwie17 added the [Status] Needs Review This PR is ready for review. label Jul 30, 2026
@louwie17 louwie17 self-assigned this Jul 30, 2026
@louwie17 louwie17 added the Enhancement Changes to an existing feature — removing, adding, or changing parts of it label Jul 30, 2026
@github-actions

github-actions Bot commented Jul 30, 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 wooa7s-1787-adapt-insights-tab-based-on-current-experience-date-selection branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack wooa7s-1787-adapt-insights-tab-based-on-current-experience-date-selection
bin/jetpack-downloader test jetpack-mu-wpcom-plugin wooa7s-1787-adapt-insights-tab-based-on-current-experience-date-selection

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

@github-actions

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!

@jp-launch-control

jp-launch-control Bot commented Jul 30, 2026 •

Copy link
Copy Markdown

Code Coverage Summary

Coverage changed in 4 files.

File Coverage Δ% Δ Uncovered
projects/packages/premium-analytics/routes/dashboard/stage.tsx 0/26 (0.00%) 0.00% 9 💔
projects/packages/premium-analytics/packages/routing/src/hooks/use-report-date-filters/use-report-date-filters.tsx 0/37 (0.00%) 0.00% 5 💔
projects/packages/premium-analytics/src/class-dashboard-section.php 34/34 (100.00%) 0.00% 0 💚
projects/packages/premium-analytics/src/dashboard-sections.php 146/152 (96.05%) 1.61% 0 💚

2 files are newly checked for coverage.

File Coverage
projects/packages/premium-analytics/routes/dashboard/config/date-filter.ts 5/5 (100.00%) 💚
projects/packages/premium-analytics/routes/dashboard/hooks/use-section-date-filter.ts 14/14 (100.00%) 💚

Full summary · PHP report · JS report

If appropriate, add one of these labels to override the failing coverage check: Covered by non-unit tests Use to ignore the Code coverage requirement check when E2Es or other non-unit tests cover the code Coverage tests to be added later Use to ignore the Code coverage requirement check when tests will be added in a follow-up PR I don't care about code coverage for this PR Use this label to ignore the check for insufficient code coveage.

@chihsuan chihsuan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the thoughtful work here! @louwie17

One integration issue seems important to surface before this ships. I tested selecting 2025 on Insights: the header, selected pill, and URL all correctly say 2025, but only Posting activity widget responds to that range.

Screen.Recording.2026-08-03.at.11.54.38.AM.mov

I think this creates a misleading section-level contract. The page says “Insights · 2025”, while most widgets still show all-time or current-year data.

Raising this for awareness, I think we should decide before shipping whether:

  1. the section-level year must filter every widget;
  2. widgets that intentionally remain all-time need explicit labels or grouping; or
  3. the global year control should wait until the remaining widget endpoints support it.

Could we capture this in a follow-up issue and clarify the intended widget-level behavior in this PR? I also left a few inline comments.

* when they lose focus, so only the active section's header is ever rendered
* and one set of controls is enough.
*/
const dateControls =

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I checked the comparison behavior locally. The comparison params survive and are re-derived for Insights, but today’s Insights widgets only request the primary range and render no deltas, so there is no visible impact.

But just wanted to say, this looks like URL hygiene for now, with a future risk if an Insights widget starts consuming comparison implicitly.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hmm yeah, at the moment it doesn't quite feel like insights would support comparison, but would be a good thing to be aware off for the time being.
Lets do this as a follow up, given this would also impact the other tabs potentially.

): DateFilterSurface {
// Null until the sections resolve. Reconciling before then would judge the
// preset against the wrong surface and undo a `?section=` deep link's preset.
const surface = section ? resolveDateFilterSurface( section.date_filter ) : null;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

minor: Would it make sense if we compare date_filter directly with DATE_FILTER_YEAR and drop the resolver?

year is the only opt-in surface, so missing or unknown values already fall through to the range UI. This removes a helper whose unknown input conflicts with the closed TS union.

*
* @return void
*
* @phan-suppress PhanPluginMixedKeyNoKey

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: Could the Phan suppression be scoped to the reported mixed-key line with @phan-suppress-next-line?

@chihsuan
chihsuan requested a review from retrofox August 3, 2026 04:01
@louwie17
louwie17 force-pushed the wooa7s-1787-adapt-insights-tab-based-on-current-experience-date-selection branch from d9af076 to 2319458 Compare August 4, 2026 12:33

@louwie17 louwie17 left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks @chihsuan for the review, I addressed your comments, this should be good for a re-review.

* when they lose focus, so only the active section's header is ever rendered
* and one set of controls is enough.
*/
const dateControls =

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Hmm yeah, at the moment it doesn't quite feel like insights would support comparison, but would be a good thing to be aware off for the time being.
Lets do this as a follow up, given this would also impact the other tabs potentially.

@louwie17
louwie17 requested a review from chihsuan August 4, 2026 13:03

@chihsuan chihsuan left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for addressing feedback! @louwie17

One thing the rebase moved, worth a look before merge: the subtitle now appends vs. Previous period whenever a comparison is applied. Could we drop comparisonPresetId from the subtitle on the year surface?

Other than that, everything looks good.

Image

louwie17 and others added 6 commits August 5, 2026 10:36
Make the date-filter surface a per-section configuration and turn it on for
Insights, which reports on whole history rather than a rolling window.

Sections gain a `date_filter` arg (`range`, the default, or `year`), exposed
in the sections REST response and its new schema. The dashboard renders
`DateYearFilter` for `year` sections and keeps `DateFiltersPanel` everywhere
else, and reconciles the shared `?preset=` param with whichever surface the
active section shows so a section switch never leaves the control unable to
represent the selection.

Builds on #50754, which shipped the year presets and the filter component
without mounting them.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAX3YkQxDLLXhKXjft6qU2
WPCOM's public-api registers the sections route from its own checkout, so a
Simple site can be served a payload built before the field existed. A required
field modelled that as impossible. `resolveDateFilterSurface` already treats a
missing value as the date-range surface, so nothing changes at runtime.

Drops the fixture lines the required field had forced into two files that have
nothing to do with date filters, and covers the now-reachable case: a section
served without the field resolves to the range surface.

The PHP side is unchanged — `Dashboard_Section::$date_filter` already defaults
to `range` and the schema already declares that default.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAX3YkQxDLLXhKXjft6qU2
The Store section is now gated on the current user's capabilities (#50889), so
the availability filter alone no longer surfaces it in the built-in sections
test.

Drop the removed `containerElement` prop from `DateFiltersPanel`, and take
trunk's `getSectionSubtitle` for the header subtitle instead of the year-only
label this branch added.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAX3YkQxDLLXhKXjft6qU2
Drop `resolveDateFilterSurface` and compare `date_filter` with the year
constant directly: `year` is the only opt-in surface, so a missing or unknown
value already falls through to the range UI, and the helper's `unknown`
parameter fought the closed union. Its coverage moves to the hook, where the
fallback is a behaviour rather than a fixture shape.

Scope the Phan suppression to the array entry it is reported on instead of the
whole function.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAX3YkQxDLLXhKXjft6qU2
The filter stands in for WooCommerce being active and the admin user satisfies
the capability check; the section needs both, so neither line is redundant.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAX3YkQxDLLXhKXjft6qU2
The year surface has no comparison control, so the header should not announce
"vs. Previous period" for a comparison the reader cannot switch off from there.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HAX3YkQxDLLXhKXjft6qU2
@louwie17
louwie17 force-pushed the wooa7s-1787-adapt-insights-tab-based-on-current-experience-date-selection branch from 1e2b1bf to 5b7dd06 Compare August 5, 2026 08:38
@louwie17
louwie17 merged commit a6e6543 into trunk Aug 5, 2026
79 of 80 checks passed
@louwie17
louwie17 deleted the wooa7s-1787-adapt-insights-tab-based-on-current-experience-date-selection branch August 5, 2026 09:58
@github-actions github-actions Bot added [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. and removed [Status] In Progress [Status] Needs Review This PR is ready for review. labels Aug 5, 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 [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. [Tests] Includes Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants