Skip to content

Premium Analytics: let other plugins register dashboard widget types - #52637

Closed
retrofox wants to merge 3 commits into
trunkfrom
update/pa-extensibility-widgets
Closed

retrofox wants to merge 3 commits into
trunkfrom
update/pa-extensibility-widgets

Conversation

@retrofox

@retrofox retrofox commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Linear: WOOA7S-2183

Proposed changes

This is the umbrella pull request for a four-step stack that lets another plugin register widget types on the Premium Analytics dashboard, from its own build and with its own translations, and moves the first real widgets out of the package.

Each step is its own pull request, based on the previous one, and each carries docs/dashboard-widgets.md as it stands after that step. This umbrella stays open as the reference for the whole arc and for the decisions it records, and closes once the last step lands.

The steps

Step 1: a registration moment (#52568, merged)

The widget type registry hydrates on its first read after init and fires jetpack_premium_analytics_register_widget_types once. A plugin with a widgets/ folder calls register_widget_types_from_manifest() with the manifest wp-build generates. register_widget_type() is the primitive, and WIDGET_API_VERSION is the contract a consumer checks before registering.

Step 2: translations per record (#52634, merged)

Every widget module record says where its catalogs live, through textdomain and i18n_manifest. The client loads each module's catalog under its own domain before importing it, whatever plugin built it.

Step 3: the first real consumer (#52635)

A new wordads-analytics package owns the Ads section and its three widgets. It builds them with wp-build against the dashboard's shared modules, which it depends on by name through workspace aliases. The WordAds module calls it outside WordPress.com, and jetpack-mu-wpcom calls it on Simple and Atomic.

Step 4: documentation (#52636)

The widgets and sections docs describe the contract after steps 2 and 3, and the README gains an entry point for extending the dashboard from another plugin.

Why

The sections stack (#52448) gave sections a registration moment, a helper and a first consumer. Widget types had the registry, the REST route and the import map, but no public registration and no moment a plugin could hook. The client loaded translations only for the package's own bundles, and nothing told a widget built against one toolkit version which package it landed on.

The rule is the one the sections follow: the package owns the dashboard, not the features. A section and its widgets belong to the code that knows the feature is there.

The first consumer is a package rather than the WordAds module because WordAds comes with Premium and higher on WordPress.com, where most sites are Simple and run no Jetpack module. A package vendored by both plugins serves the widgets everywhere the section exists.

How a plugin registers widget types

use const Automattic\Jetpack\PremiumAnalytics\WIDGET_API_VERSION;
use function Automattic\Jetpack\PremiumAnalytics\register_widget_types_from_manifest;

add_action(
	'jetpack_premium_analytics_register_widget_types',
	static function ( $registry ) {
		if ( version_compare( WIDGET_API_VERSION, '2', '>=' ) ) {
			return;
		}

		// The generated build registers the widget script modules on the spot after init.
		require_once __DIR__ . '/build/build.php';

		register_widget_types_from_manifest(
			my_plugin_get_registered_widget_modules(),
			array(
				'textdomain'    => 'my-plugin',
				'i18n_manifest' => plugins_url( 'build/i18n-manifest.json', __FILE__ ),
			),
			$registry
		);
	},
	20
);

The plugin's build keeps @jetpack-premium-analytics/* external (wpPlugin.externalNamespaces), so the shared modules resolve through the page import map to the single copy the dashboard registers. wp-build does that only when it finds each package installed under its name, so a plugin in this monorepo declares them through workspace aliases:

"@jetpack-premium-analytics/widgets-toolkit": "workspace:@automattic/jetpack-premium-analytics-widgets-toolkit@*"

📸 Screenshot placeholder: the page import map with the dashboard modules and a plugin's widget modules

Decisions recorded here

Global registration

Widget types register globally, like block types, with no provider field. The name's namespace and the text domain are the provenance.

Helper first

Like core's Abilities API, register_widget_types_from_manifest() and register_widget_type() write to the main registry, and the action hands the registry over for lookups.

The version constant

WIDGET_API_VERSION ships with step 1. The core-shaped form, apiVersion in widget.json, is an upstream ask.

Translations per record

Translations travel with each record rather than with each build, because a record is what the client has when it imports.

Renamed widget types

The Ads widgets are wordads/*. A layout persisted with the old jpa/wordads-* names shows its tiles as unavailable until it is reset. Ads is outside the customer preview, so only internal sites carry such layouts.

Dashboard context later

The widget-type reads take no dashboard argument yet. The route is global and the hook hangs off the package's page, and both can gain the argument later without breaking a consumer.

Dependencies by name

The dashboard's internal packages become workspace members where they are, so consumers depend on them by name instead of reaching into the package's folders. Package names must be @automattic/*, so the module ids point to them through aliases. Moving them to projects/js-packages later keeps the same dependency lines.

Follow-ups, outside this stack

The mirror repository Automattic/jetpack-wordads-analytics and its Packagist entry have to exist before step 3 merges.

The moved widgets need stories and JS tests again, since theirs depended on the dashboard package's harness. Renamed widget types need an alias in persisted layouts, tracked in WOOA7S-2200.

The generated registration drops a widget's classic script dependencies, so a consumer widget relies on the dashboard page loading them.

A consumer outside the monorepo, such as a Store section owned by WooCommerce, needs the dashboard's JS API published, which means moving it to projects/js-packages.

A dashboard registry and per-dashboard persistence can wait for a second dashboard. The preview allow-list is still a list inside the package, and the owner of a section should hold that key.

Related product discussion/links

The sections stack this continues: #52448. Linear: WOOA7S-2183.

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

No.

Testing instructions

Each step has its own. For the whole arc, use a connected site with the WordAds module active and the Ads section opened out of the preview scope:

jetpack install -r plugins/jetpack packages/jetpack-mu-wpcom packages/premium-analytics packages/wordads-analytics
jetpack build packages/wp-build-polyfills packages/premium-analytics packages/wordads-analytics plugins/jetpack

GET /wp-json/wpcom/v2/widget-modules lists the three wordads/* types, with modules under jetpack-wordads-analytics/widgets/ and the text domain jetpack-wordads-analytics-pkg. The page import map carries those ids, and the Ads section renders the three widgets from the package's build.

📸 Screenshot placeholder: the Ads section rendered from the package's build

@github-actions

github-actions Bot commented Sep 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 (Jetpack or WordPress.com Site Helper), and enable the update/pa-extensibility-widgets branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack update/pa-extensibility-widgets
bin/jetpack-downloader test jetpack-mu-wpcom-plugin update/pa-extensibility-widgets

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

github-actions Bot commented Sep 22, 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!


Jetpack plugin:

The Jetpack plugin has different release cadences depending on the platform:

  • WordPress.com Simple releases happen as soon as you deploy your changes after merging this PR (PCYsg-Jjm-p2).
  • WoA releases happen weekly.
  • Releases to self-hosted sites happen monthly:
    • Scheduled release: October 6, 2026

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


Mu Wpcom plugin:

  • Next scheduled release: WordPress.com Simple releases happen semi-continuously (PCYsg-Jjm-p2)

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


Wpcomsh plugin:

  • Next scheduled release: Atomic deploys happen twice daily on weekdays (p9o2xV-2EN-p2)

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


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.

@jp-launch-control

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

Copy link
Copy Markdown

Code Coverage Summary

Coverage changed in 4 files.

File Coverage Δ% Δ Uncovered
projects/packages/jetpack-mu-wpcom/src/features/premium-analytics/wordads-section.php 3/11 (27.27%) -69.02% 7 💔
projects/packages/premium-analytics/packages/data/src/hooks/use-stats-wordads.ts 0/2 (0.00%) -100.00% 2 ❤️‍🩹
projects/packages/premium-analytics/src/default-dashboard-sections.php 320/323 (99.07%) -0.06% 0 💚
projects/plugins/jetpack/modules/wordads/php/class-wordads-premium-analytics.php 4/5 (80.00%) -5.19% -3 💚

2 files are newly checked for coverage.

File Coverage
projects/packages/wordads-analytics/src/class-analytics-dashboard.php 43/52 (82.69%) 💚
projects/packages/premium-analytics/packages/widgets-toolkit/src/jetpack-script-data.d.ts 0/0 (—%) 🤷

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.

builds wordads/* with wp-build and registers the Ads section and widget types; module and mu-wpcom call it
PA's internal packages join the workspace; the Ads package depends on them through aliases, with no ../ paths
widgets doc: translations per record and the Ads package as the real consumer; README extension entry point
@retrofox
retrofox force-pushed the update/pa-extensibility-widgets branch from 71a25d5 to 74d24a7 Compare September 24, 2026 09:39
@retrofox

Copy link
Copy Markdown
Contributor Author

All subtasks have been addressed. Closing this PR.

@retrofox retrofox closed this Sep 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant