Skip to content

Premium Analytics: move the Ads widgets to the jetpack-ads package - #52635

Merged
retrofox merged 24 commits into
trunkfrom
update/pa-extensibility-wordads-package
Sep 28, 2026
Merged

retrofox merged 24 commits into
trunkfrom
update/pa-extensibility-wordads-package

Conversation

@retrofox

@retrofox retrofox commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Fixes WOOA7S-2188

Proposed changes

Step 3 of 4 of the widget-type extensibility stack (umbrella: #52637).

The Ads section and its three widgets leave the Premium Analytics package and move to their own package, jetpack-ads.

It is the first real consumer of the widget registration added in #52568 and #52634, and it is rebased on trunk now that both are in.

What changes

A new package, projects/packages/ads, owns the Ads section and its three widgets: chart tabs, highlights, and earnings history.
They register as wordads/chart-tabs, wordads/highlights and wordads/earnings-history, so the namespace names the owner.

The package registers everything through the dashboard's public API: the section with its title and default layout, and the widget types from the manifest it generates.
The WordAds module and jetpack-mu-wpcom no longer declare the section themselves and only call the package.

The module does it outside WordPress.com, and mu-wpcom does it on Simple and Atomic when the plan includes WordAds. The Premium Analytics package loses the three widgets and the Ads layout helper.

The changes the trunk made to those widgets in the meantime (#52683, #52690, #52714, #52794) moved with them.

A new js-package, projects/js-packages/premium-analytics-sdk, holds the SDK the widgets import, and the dashboard provides it at runtime. More on this below.

Why a package

WordAds comes with Premium and higher on WordPress.com, where most sites are Simple and run no Jetpack module.

The Jetpack module reaches self-hosted and Atomic sites, and jetpack-mu-wpcom registers on Simple and Atomic from the copy the Jetpack plugin bundles, as #52717 does for Premium Analytics; the package is test-only there.

AFAIK, a Composer package is the only unit both callers can share.

How the package uses the dashboard's modules

The widgets import the dashboard's SDK by name, like any package:

import { WidgetRoot, WidgetState, useStatsWordAdsStats } from '@automattic/jetpack-premium-analytics-sdk';

That name is three things at once: an npm package, an import specifier and a script module id. Each side of the boundary handles one step.

1. The SDK package is the contract. projects/js-packages/premium-analytics-sdk is a private workspace package. It holds the types of what the dashboard provides (src/index.d.ts) and a wpScriptModuleExports entry, which marks it as a script module. It has no build: the implementation is the dashboard's. Its src/index.js only throws, so a build that bundles it by mistake fails loudly instead of shipping a second copy.

2. The Ads package builds with wp-build, unchanged. It depends on the SDK with workspace:* and lists the automattic scope as an external namespace:

"dependencies": { "@automattic/jetpack-premium-analytics-sdk": "workspace:*" },
"wpPlugin": { "externalNamespaces": { "automattic": { "global": "automattic", "handlePrefix": "automattic" } } }

wp-build's externals plugin resolves @automattic/jetpack-premium-analytics-sdk from node_modules, sees wpScriptModuleExports, and leaves the import external, recorded as a module dependency of the widget. It is the same rule it applies to @wordpress/*; nothing in wp-build changed. Each widget's asset ends up like this:

'module_dependencies' => array( array( 'id' => '@automattic/jetpack-premium-analytics-sdk', 'import' => 'static' ) ),

3. The dashboard provides the implementation. packages/sdk is a facade module wp-build builds as @jetpack-premium-analytics/sdk: re-exports of the pieces widgets need from the dashboard's own modules (widgets toolkit, data, fields, dates, shared primitives). src/sdk-module.php registers that same file a second time, under the SDK's name. As with Connection (#38877), the package that owns the code provides the bundle.

wp_register_script_module( '@automattic/jetpack-premium-analytics-sdk', $build_url . 'modules/sdk/index.min.js', $module_dependencies, $version );

4. The browser joins the two. The page import map maps the SDK name to the facade, and the facade's dependencies to the dashboard's modules, so a widget runs on the same module instances the dashboard renders with: one React, one toolkit, one query client.

Nothing in the Ads package points at another project: no ../ path in its package.json or tsconfig.json, and the dashboard's internal packages stay out of the workspace (reverted in 05ad025). The runtime shape is the one Connection has had since #38877, and the one Core uses for @wordpress/interactivity: import by name, external in the build, bundle served by the package that owns the code. The SDK's npm package holds only the types for now because its implementation is the dashboard's own modules, re-exported by the facade; moving those internals into js-packages, so the SDK can carry real source, is a separate decision.

How it loads in the browser

A widget's code loads only when the dashboard renders it, and a shared module already on the page isn't downloaded again.

The three Ads bundles weigh between 3.5 and 4.9 KB minified, because the toolkit and the data layer stay out of them.

image

Mirror repository

The mirror repository Automattic/jetpack-ads and its Packagist entry are in place. The name is the product-agnostic one, so the package can grow into the whole WordAds module without another rename.

Follow-ups

The three widget tests and their stories depended on the Premium Analytics test harness, so they leave with this move. The Ads package needs its own Jest and Storybook setup to bring them back, with the empty-CPM case from #52690; the issue follows once we settle how widget test setups are shared. The data-layer tests stay in Premium Analytics.

A layout saved with the old jpa/wordads-* names shows its tiles as unavailable until you reset it.

Ads is outside the customer preview, so only internal sites have such layouts. WOOA7S-2200 tracks a rename map for widget types.

The SDK contract is loosely typed for now. It gets precise types, and an audit of what it exposes, before the package is published to npm.

Related product discussion/links

Umbrella of this stack: #52637. Steps 1 and 2: #52568 and #52634. Linear: WOOA7S-2183 for the stack and WOOA7S-2188 for this step.

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

No.

Testing instructions

Set up

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

Ads is outside the customer preview, so open it with this line in a mu-plugin before testing:

add_filter( 'jetpack_premium_analytics_dashboard_preview_scope', '__return_true' );

Use a connected site with the WordAds module active, as an administrator.

Automated tests

jetpack test php packages/ads
jetpack test php packages/premium-analytics
jetpack test php packages/jetpack-mu-wpcom
jetpack docker phpunit jetpack -- --filter WordAds_Premium_Analytics_Test

1. The widget types are registered

Request GET /wp-json/wpcom/v2/widget-modules. It lists the three wordads/* types, with their render modules under jetpack-ads/widgets/ and the text domain jetpack-ads-pkg.

image

2. The Ads section renders

Open the dashboard and go to Ads. The section, titled "Ads performance", shows the three widgets.

image

3. The shared modules load once

In the network tab, the render modules come from jetpack_vendor/automattic/jetpack-ads/build/widgets/, the SDK resolves to premium-analytics/build/modules/sdk/index.min.js, and widgets-toolkit/index.min.js is requested only once.
The console shows no Failed to resolve module specifier error.

image image

4. The picker offers the widgets

Enter edit mode and open the widget picker. The three Ads widgets appear under Stats.

image

5. Without WordAds, the section is gone

Turn the WordAds module off. The Ads section disappears, and the three types are no longer listed.

Screen.Recording.2026-09-24.at.11.48.59.AM.mov

6. Layouts saved before this change

A layout saved with jpa/wordads-* instances shows "Widget is no longer available" tiles until it is reset.

7. The rest of the dashboard is unchanged

A Premium Analytics report with a CSV export button still shows it.

8. mu-wpcom carries no copy of the package

jetpack build plugins/mu-wpcom-plugin

jetpack_vendor/automattic/jetpack-ads is absent from the build, as #52717 does for Premium Analytics; the mu-wpcom tests still run against it as a test-only dependency.

@retrofox retrofox added Enhancement Changes to an existing feature — removing, adding, or changing parts of it [Status] In Progress labels Sep 22, 2026
@retrofox retrofox self-assigned this Sep 22, 2026
@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-wordads-package branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack update/pa-extensibility-wordads-package
bin/jetpack-downloader test jetpack-mu-wpcom-plugin update/pa-extensibility-wordads-package

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 6 files. Only the first 5 are listed here.

File Coverage Δ% Δ Uncovered
projects/packages/jetpack-mu-wpcom/src/features/wpcom-admin-bar/wpcom-admin-bar.php 154/296 (52.03%) -5.07% 15 💔
projects/packages/jetpack-mu-wpcom/src/features/premium-analytics/wordads-section.php 6/11 (54.55%) -41.75% 4 💔
projects/packages/premium-analytics/packages/data/src/hooks/use-stats-wordads.ts 0/2 (0.00%) -100.00% 2 ❤️‍🩹
projects/packages/premium-analytics/src/class-analytics.php 153/166 (92.17%) 0.05% 0 💚
projects/packages/premium-analytics/src/default-dashboard-sections.php 320/323 (99.07%) -0.06% 0 💚

4 files are newly checked for coverage.

File Coverage
projects/packages/premium-analytics/packages/sdk/src/conformance.ts 0/1 (0.00%) 💔
projects/packages/premium-analytics/src/sdk-module.php 15/25 (60.00%) 💚
projects/packages/ads/src/class-analytics-dashboard.php 43/51 (84.31%) 💚
projects/packages/premium-analytics/packages/sdk/src/index.ts 0/0 (—%) 🤷

Full summary · PHP report · JS report

Coverage check overridden by Coverage tests to be added later Use to ignore the Code coverage requirement check when tests will be added in a follow-up PR .

@retrofox
retrofox added this pull request to stack #52692 September 23, 2026 08:53
@retrofox
retrofox force-pushed the update/pa-extensibility-wordads-package branch from 8f77bd5 to cc5be17 Compare September 23, 2026 14:36
@retrofox
retrofox force-pushed the update/pa-extensibility-wordads-package branch from cc5be17 to a4999b7 Compare September 23, 2026 14:48
@retrofox
retrofox force-pushed the update/pa-extensibility-wordads-package branch 2 times, most recently from c153cdb to ff48b34 Compare September 23, 2026 15:57
@retrofox
retrofox marked this pull request as ready for review September 23, 2026 16:47
louwie17
louwie17 previously approved these changes Sep 25, 2026

@louwie17 louwie17 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.

Thanks for the updates @retrofox, the SDK approach is a lot cleaner, and it's nice to see the widgets only import @automattic/jetpack-premium-analytics-sdk now. This looks good locally and I will have to re-test it on Simple, although this may have to be merged first to do a full testing.

I did notice all the SDK types are any at the moment, meaning the widgets lost their type checking in the move, and together with the Jest tests being a follow up nothing checks them right now. I presume this will be a follow up?

I left a few small inline comments, happy for them to be follow ups. One thing to make sure of before merging is the Automattic/jetpack-wordads-analytics mirror repo and Packagist entry, as far as I can tell it doesn't exist yet and the Jetpack plugin requires the package.

Overall this all looks good, and the work is also still behind a feature flag, so this should be good to merge from my perspective 🚢

export declare const PRESET_LAST_12_MONTHS: string;

// Data.
export declare function useStatsWordAdsStats( ...args: any[] ): any;

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.

Should the WordAds specific hooks and components (useStatsWordAdsStats, useStatsWordAdsEarnings, EarningsHistoryList, flattenEarningsBreakdown) live in the SDK long term? Given this is meant to become the public API, removing them later would be a breaking change. I presume these will be moving to the WordAds package as well?

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.

Agreed. They're in because the widgets need them and the SDK doesn't expose the generic report hooks they're built on yet; the two earnings ones are shared with the Earnings report still in PA.

They leave for the Ads package with that report, at no compat cost since the SDK is private until the audit. Marked provisional in the .d.ts (c5df75e).

*
* @return bool
*/
private static function widget_contract_moved_on() {

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.

Could we add a test for the case where WIDGET_API_VERSION isn't defined yet, like on the sections REST route? That's the case 8981f4b fixed, and the current tests always load widget-types.php, so it would be easy for it to come back. Can also be a follow up.

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.

Done in cabc916: Analytics_Dashboard_Without_Widget_Types_Test, one process per test so the constant stays undefined. It covers both branches: the section registers, the widget types wait.

* @param bool $minified Whether to serve the minified bundle.
* @return array|null `src`, `deps` and `version` for `wp_register_script_module()`, or null when the registry has no facade.
*/
function get_sdk_module_registration( array $modules, array $constants, $build_dir, $minified = true ) {

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.

A small nit, this is only used by the registration below and its tests, should we mark it @internal so it doesn't become part of the package's public surface?

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.

Done in 3616913.

the name scales to the whole WordAds module; mirror Automattic/jetpack-ads
@retrofox retrofox changed the title Premium Analytics: move the Ads widgets to a WordAds package Premium Analytics: move the Ads widgets to the jetpack-ads package Sep 25, 2026
@retrofox

Copy link
Copy Markdown
Contributor Author

Thanks Lourens. The round is in cabc916..c5df75e, replies inline.

Types: yes, a follow-up. The real types live in PA's internal packages, so the plan is a PA build step that emits a bundled .d.ts from the packages/sdk facade into the js-package, instead of hand-written declarations. Same round as the Jest harness, once the internals question is settled with the team.

Mirror: the package is automattic/jetpack-ads now (58005d4). The request to crew is out; nothing merges before it exists.

The push dismissed your approval. Could you re-approve once you've looked at the round?

PHPUnit feeds the child process from stdin; PHP 7.4 warns on the empty needle
@retrofox retrofox added the Coverage tests to be added later Use to ignore the Code coverage requirement check when tests will be added in a follow-up PR label Sep 25, 2026
louwie17
louwie17 previously approved these changes Sep 28, 2026

@louwie17 louwie17 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.

Thanks @retrofox, the updates look good, and thanks for adding the test for the sections route and marking the provisional exports. This still looks good locally with the rename to jetpack-ads. Good to merge from my perspective 🚢

…ity-wordads-package

# Conflicts:
#	projects/packages/ads/widgets/wordads-chart-tabs/render.tsx
#	projects/packages/premium-analytics/widgets/wordads-chart-tabs/stories/wordads-chart-tabs-widget.stories.tsx

@louwie17 louwie17 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.

Thanks @retrofox, the trunk merge and changelog updates look good, and this still tests well locally. This is still good to go!

@retrofox
retrofox merged commit 82e0bc6 into trunk Sep 28, 2026
120 checks passed
@retrofox
retrofox deleted the update/pa-extensibility-wordads-package branch September 28, 2026 09:14
@github-actions github-actions Bot added the [Status] UI Changes Add this to PRs that change the UI so documentation can be updated. label Sep 28, 2026
dognose24 added a commit that referenced this pull request Sep 29, 2026
…ds is on

Rebased onto the registrant #52635 moved into jetpack-mu-wpcom: the plan
feature alone still decided there, so every Premium-and-up Simple or Atomic
site saw an Ads tab whether or not WordAds was ever turned on. The gate now
also requires WordAds to be on, read as classic Stats reads it: the approval
stickers on Simple, the WordAds module on Atomic.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
dognose24 added a commit that referenced this pull request Sep 29, 2026
…ption-2

Re-apply the Adjustments link change on the widget's new home in packages/ads
after #52635; its test and stories were dropped in that move.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
dognose24 added a commit that referenced this pull request Sep 29, 2026
The Earnings History widget lives in packages/ads since #52635, which the
standalone plugin does not bundle.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
dognose24 added a commit that referenced this pull request Sep 29, 2026
…ds is on (#52903)

* Premium Analytics: show the Ads tab on WordPress.com only while WordAds is on

Rebased onto the registrant #52635 moved into jetpack-mu-wpcom: the plan
feature alone still decided there, so every Premium-and-up Simple or Atomic
site saw an Ads tab whether or not WordAds was ever turned on. The gate now
also requires WordAds to be on, read as classic Stats reads it: the approval
stickers on Simple, the WordAds module on Atomic.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Say the WordPress.com gate is plan plus WordAds on, in docs and comments

The docs, the sections diagram, the Ads package's README and docblock and
the module registrant's comments still described the plan-only gate. The
Atomic comment also claimed to match Odyssey, which reads the approval
stickers through the site endpoint; the rule is that a site with the module
off is not running ads.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
dognose24 added a commit that referenced this pull request Oct 1, 2026
…2752)

* Premium Analytics: link to adjustments as text with a count badge

An alternative to the badge that is itself the link: the footer reads
"Adjustments" with the row count in a neutral badge beside it, so the
link has its own text and the badge stays a label.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Drop the premium-analytics plugin changelog entry

The Earnings History widget lives in packages/ads since #52635, which the
standalone plugin does not bundle.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

* Keep the ReportLink hover underline off the badge

The underline sat on the link, so it ran through the count badge too.
The label now carries it, and children render after the label.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Coverage tests to be added later Use to ignore the Code coverage requirement check when tests will be added in a follow-up PR Docs Enhancement Changes to an existing feature — removing, adding, or changing parts of it [Feature] Ad [JS Package] Premium Analytics Api [JS Package] Premium Analytics Sdk [mu wpcom Feature] Premium Analytics [Package] Ad aka WordAds [Package] Ads [Package] Jetpack mu wpcom WordPress.com Features [Package] Premium Analytics [Package] Wordads Analytics [Package] Wp Build Polyfills [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Plugin] mu wpcom jetpack-mu-wpcom plugin [Plugin] Premium Analytics [Plugin] Wpcomsh RNA [Status] Needs Testing We need to add this change to the testing call for this month's release [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.

4 participants