Skip to content

Premium Analytics: share Stats widget error descriptions - #50729

Merged
chihsuan merged 3 commits into
worktree-wooa7s-1770-api-error-statusfrom
wooa7s-1649-describe-error-dependent
Jul 27, 2026
Merged

chihsuan merged 3 commits into
worktree-wooa7s-1770-api-error-statusfrom
wooa7s-1649-describe-error-dependent

Conversation

@chihsuan

@chihsuan chihsuan commented Jul 22, 2026 •

Copy link
Copy Markdown
Member

Fixes WOOA7S-1649

Proposed changes

Stats widgets currently build their error-state descriptors independently, which duplicates policy and has allowed details such as missing actions to drift. Now that WOOA7S-1770 preserves the HTTP status on failed Stats requests, this PR centralizes the UI decision in the widgets toolkit.

  • Add a shared describeError mapper and unit tests.
  • Show neutral, non-retryable copy for 403 responses and retryable copy for all other failures, including 404. The proxy's no_connection 403 stays retryable — a broken Jetpack connection can heal, unlike a permission gate.
  • Widgets pass the retryable copy as a full sentence instead of a noun fragment interpolated into a shared frame, so translators see the whole sentence and languages with case/gender agreement can decline it correctly.
  • Migrate Devices, Top Platforms, UTM Insights, and Search Terms to the shared mapper while retaining their existing partial-data guards; the view hooks now gate error with the same predicate as isError so the two fields can't disagree.
  • Document the shared policy and add a patch changelog entry.

Related product discussion/links

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

No.

Testing instructions

  • Build Premium Analytics with its dependencies (pnpm jetpack build plugins/premium-analytics --deps) and open the Premium Analytics dashboard in wp-admin.
  • To force the Devices / Top Platforms report requests to fail, drop this mu-plugin into wp-content/mu-plugins/. It reads a fake_err flag off the dashboard URL (via the request referer), so you can switch modes per page load without touching stored site state:
mu-plugin: force stats/devices/* errors
<?php
/**
 * Force Premium Analytics stats/devices/* requests to fail, driven by a
 * `fake_err` param on the wp-admin dashboard URL (read back off the referer).
 * Modes: 403 | 403nc (no_connection) | 500. Remove the param for normal data.
 */
add_filter(
	'rest_pre_dispatch',
	function ( $result, $server, $request ) {
		if ( ! preg_match( '#^/jetpack-premium-analytics/v1/proxy/v[0-9.]+/stats/devices/#', $request->get_route() ) ) {
			return $result;
		}

		$query = wp_parse_url( $_SERVER['HTTP_REFERER'] ?? '', PHP_URL_QUERY );
		parse_str( (string) $query, $args );

		switch ( $args['fake_err'] ?? '' ) {
			case '403':
				return new WP_Error( 'rest_forbidden', 'Simulated permission failure.', array( 'status' => 403 ) );
			case '403nc':
				return new WP_Error( 'no_connection', 'Simulated broken Jetpack connection.', array( 'status' => 403 ) );
			case '500':
				return new WP_Error( 'server_error', 'Simulated server failure.', array( 'status' => 500 ) );
		}

		return $result;
	},
	10,
	3
);
  • Open the dashboard with &fake_err=403 appended to the URL. Confirm Devices and Top Platforms show “You don't have access to this data.” with no Retry button. 403s are not auto-retried, so the error shows immediately.
Screenshot 2026-07-22 at 4 06 42 PM
  • Open with &fake_err=403nc. Confirm the widgets show the retryable copy with a Retry button instead — the proxy's no_connection 403 stays retryable.
  • Open with &fake_err=500. Confirm Devices shows “We couldn't load device data. Please try again in a moment.” with a Retry button (Top Platforms says “platform data”). Non-403 failures go through React Query's three auto-retries first, so expect ~8 seconds of skeleton before the error appears — and keep the window focused, since React Query pauses retries while the tab is hidden.
Screenshot 2026-07-22 at 4 07 20 PM
  • With the error state showing, drop the flag without reloading — run history.replaceState(null, '', location.href.replace(/&fake_err=\w+/, '')) in the DevTools console — then click Retry. Confirm the request runs again, succeeds, and the widget recovers to its chart.

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

github-actions Bot commented Jul 22, 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 (WordPress.com Site Helper), and enable the wooa7s-1649-describe-error-dependent branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack-mu-wpcom-plugin wooa7s-1649-describe-error-dependent

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!

@chihsuan
chihsuan force-pushed the wooa7s-1649-describe-error-dependent branch from aee027d to 90dc22e Compare July 22, 2026 07:48
@jp-launch-control

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

Copy link
Copy Markdown

Code Coverage Summary

No summary data is available for parent commit 5839cb6, so cannot calculate coverage changes. 😴

If that commit is a feature branch rather than a trunk commit, this is expected. Otherwise, this should be updated once coverage for 5839cb6 is available.

Full summary · PHP report · JS report

@layoutd layoutd 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! Manually tested the error states and retry recovery; everything works as expected, left one non-blocking comment about storybook.

error: unknown,
{ retryDescription, onRetry }: DescribeErrorOptions
): WidgetStateError {
if ( getApiErrorStatus( error ) === 403 && getApiErrorCode( error ) !== 'no_connection' ) {

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.

Non-blocking: The Storybook error mocks return a 403, so these stories no longer show Retry as their descriptions claim. Maybe update the descriptions and add a retryable 500/no_connection story?

@chihsuan chihsuan Jul 27, 2026 •

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch — confirmed. Both mock helpers reject with a 403 whose code isn't no_connection, so those four stories were rendering the neutral no-access copy while their descriptions still promised a Retry.

Fixed in edc2563

@chihsuan
chihsuan merged commit 64bc152 into worktree-wooa7s-1770-api-error-status Jul 27, 2026
69 of 70 checks passed
@chihsuan
chihsuan deleted the wooa7s-1649-describe-error-dependent branch July 27, 2026 03:21
@github-actions github-actions Bot removed the [Status] Needs Review This PR is ready for review. label Jul 27, 2026
chihsuan added a commit that referenced this pull request Jul 27, 2026
* Premium Analytics: keep HTTP status on failed Stats API requests

* Premium Analytics: parse error Responses that apiFetch rejects, keep status on invalid JSON

* Premium Analytics: cover register guard, non-object bodies, url unbounded queries

* Premium Analytics: share Stats widget error descriptions (#50729)

* refactor: share Stats widget error descriptions

* fix: keep no_connection 403 retryable, gate hook errors, use full-sentence retry copy

* test: add retryable error stories for the shared Stats error mapper

* Update projects/packages/premium-analytics/changelog/fix-stats-api-error-status

Co-authored-by: Justin P <228780+layoutd@users.noreply.github.com>

* fix: register Stats error-status middleware from the data package

WP 7.0's Core boot ignores initModules in initSinglePage(), so the app's
init() module never runs there and the middleware was not installed.
Register it next to the retry policy that reads the status instead.

---------

Co-authored-by: Justin P <228780+layoutd@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants