Skip to content

feat(reader-activation): replace RAS auto-enable with manual toggle#196

Open
miguelpeixe wants to merge 12 commits into
mainfrom
nppd-1066-allow-ras-to-be-active-with-less-requisites
Open

feat(reader-activation): replace RAS auto-enable with manual toggle#196
miguelpeixe wants to merge 12 commits into
mainfrom
nppd-1066-allow-ras-to-be-active-with-less-requisites

Conversation

@miguelpeixe
Copy link
Copy Markdown
Member

@miguelpeixe miguelpeixe commented Jun 2, 2026

All Submissions:

Changes proposed in this Pull Request:

Closes NPPD-1066.

Reworks Audience Management (RAS) setup so it can be enabled with far fewer prerequisites, and reorganizes the wizard around an explicit reader‑revenue platform selection. RAS no longer auto‑enables based on a fully‑configured plugin stack; an administrator picks a platform, and Audience Management is enabled as part of that choice, regardless of which optional plugins are installed.

Platform selection (first‑run step)

  • The Audience wizard opens a three‑option platform chooser — Newspack (full WooCommerce stack), RevEngine (News Revenue Hub / donate block), and Other (bring‑your‑own integrations) — rendered in the standard wizard header/layout. It appears whenever no platform has been chosen yet.
  • Selecting a platform persists the reader‑revenue platform, enables Audience Management, and auto‑installs that platform's plugins (Newspack → WooCommerce, WooCommerce Subscriptions, Newspack Blocks; RevEngine → Newspack Blocks; Other → none), then advances to the configuration page.
  • Plugin installation is non‑blocking: if a plugin can't be auto‑installed (e.g. WooCommerce Subscriptions, which Newspack cannot install automatically), the installer surfaces the per‑plugin message and a Continue button instead of waiting indefinitely.
  • The currently‑selected platform is marked with a "Selected" badge.

Enable / disable

  • The enable/disable toggle now lives on the platform screen (not the configuration page, where it was easy to flip accidentally). First‑run enabling is implicit in selecting a platform; the toggle is shown when returning to the screen.
  • Disabling prompts a confirmation modal (destructive action). Enabling is immediate.
  • A site with Audience Management disabled lands on the platform screen (rather than the active‑looking configuration page), showing the current platform's "Selected" badge and the toggle.

Tabs

  • The Checkout & Payment tab is shown only for the Newspack and RevEngine platforms; for "Other" it is hidden. The inline platform selector was removed from that tab (it is now the first‑run chooser).

Configuration page cleanup

  • The prerequisites checklist is trimmed and reordered to: Transactional Emails → Legal Pages → reCAPTCHA → ESP. The Reader Revenue and Audience Management Campaign prerequisites were removed, and ESP appears only when Newspack Newsletters is installed.
  • Any of the selected platform's required/recommended plugins that are still missing are surfaced on the configuration page (with install actions), so they can be completed there even if the chooser's install didn't finish.

Plugin independence

  • Prerequisites are an informational checklist; the "Skip" buttons and the "waiting for all settings" disabled‑action state are gone. The skip subsystem is removed: Reader_Activation::skip() / is_skipped() / is_ras_ready_to_configure(), the /audience-management/skip REST route, the SKIP_CAMPAIGN_SETUP_OPTION constant, and the is_skipped_campaign_setup localized field.
  • The now‑unused Reader_Activation::is_reader_revenue_ready() helper (only consumed by the removed Reader Revenue prerequisite) and other dead code (an unused donation_settings read in Donations::remove_donations_from_cart(), the never‑set is_unavailable prerequisite branch) are removed.
  • Newsletters‑dependent controls (post‑checkout newsletter signup, ESP Advanced Settings) gate on Newspack Newsletters being installed.
  • Reader_Activation::setup_nav_menu() no longer requires WooCommerce for the anonymous Sign In link.
  • The Audience → Donations submenu hides when neither WooCommerce is installed nor NRH is the donations platform.

Integrations Settings flag (separate concern, included here)

  • When the NEWSPACK_INTEGRATIONS_SETTINGS_ENABLED constant is defined and truthy (the upcoming dedicated Integrations admin area), the Sync contacts to ESP ActionCard on the Audience configuration page is hidden — including its per‑ESP settings (Mailchimp / ActiveCampaign / Constant Contact), the "Sync user account deletion" checkbox, and the metadata fields. The save‑time validation that alerts on empty audience / master‑list IDs is suppressed in that mode so a previously‑saved sync_esp = true can't trap users on an alert for a section they can no longer see. The "ESP Advanced Settings" section header and the "Newsletter subscription text on registration" control above remain visible because they aren't about ESP sync.

Migration

  • No upgrade migration: already‑enabled sites keep enabled = true. The legacy newspack_reader_activation_*_skipped options are left in the database, intentionally unread.
  • Pre‑existing read‑time rewrite of the deprecated 'stripe' platform to 'wc' is preserved in Donations::get_platform_slug(). Sites that previously stored 'stripe' will surface as platform‑selected (wc) on first run under the new chooser — they will not see the chooser unless Audience Management is explicitly disabled.

How to test the changes in this Pull Request:

  1. First run: On a site with no reader‑revenue platform chosen, open Audience. Confirm a platform chooser (Newspack / RevEngine / Other) renders in the wizard layout instead of the configuration page.
  2. Select Other. Confirm Audience Management is enabled, no plugins are installed, the Checkout & Payment tab is absent, and you land on the configuration page.
  3. Select Newspack (on a site without WooCommerce). Confirm it installs WooCommerce and Newspack Blocks, that WooCommerce Subscriptions reports it must be installed manually, and that a Continue button appears (no hang). Continue and confirm the Checkout & Payment tab is present.
  4. Missing plugins: On the configuration page with the Newspack platform selected but WooCommerce/Subscriptions not installed, confirm they are listed as recommended/missing with install actions.
  5. Prerequisites: Confirm the checklist shows Transactional Emails → Legal Pages → reCAPTCHA, with ESP appearing only when Newspack Newsletters is installed, and no Reader Revenue or Campaign‑defaults items.
  6. Disable + confirm: From the configuration page, click Change to open the platform screen; toggle Audience Management off and confirm a confirmation modal appears before it is disabled.
  7. Disabled landing: With Audience Management disabled, reload the wizard. Confirm it lands on the platform screen (not the configuration page), the previously‑selected platform shows a "Selected" badge, and the toggle reads "disabled".
  8. Re‑enable: Toggle Audience Management on (or re‑select the platform) and confirm you move forward to the configuration page.
  9. Front‑end / menus: With WooCommerce not installed and RAS enabled, confirm the Sign In link renders for anonymous visitors; confirm the Audience → Donations submenu is hidden until WooCommerce is installed or NRH is the platform.
  10. Regression: On a site already enabled with all plugins present, confirm no regression in the wizard, reader auth, or RAS‑dependent features.

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes, as applicable?
  • Have you successfully run tests with your changes locally?

@miguelpeixe miguelpeixe requested a review from a team as a code owner June 2, 2026 14:48
@miguelpeixe miguelpeixe marked this pull request as draft June 2, 2026 15:43
@miguelpeixe miguelpeixe self-assigned this Jun 2, 2026
@miguelpeixe miguelpeixe marked this pull request as ready for review June 2, 2026 20:11
@miguelpeixe miguelpeixe requested a review from chickenn00dle June 2, 2026 20:11
@miguelpeixe miguelpeixe force-pushed the nppd-1066-allow-ras-to-be-active-with-less-requisites branch from 15fa83a to 48cadff Compare June 4, 2026 17:20
@chickenn00dle chickenn00dle self-assigned this Jun 5, 2026
Copy link
Copy Markdown
Contributor

@chickenn00dle chickenn00dle left a comment

Choose a reason for hiding this comment

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

Some review notes from a pass over the diff — all non-blocking (no blockers found). 👍

The skip-subsystem / auto-enable removal looks clean (no leftover callers anywhere in the repo), the REST permission/validation/sanitization checks are intact, and CI is green. The inline comments below are 4 suggestions + a couple of nits — edge-case hardening and polish.

One non-code note: the PR description lists NEWSPACK_INTEGRATIONS_SETTINGS_ENABLED / Audience_Integrations::is_enabled() as "new", but they already exist on main — this PR wires up their consumption, so a one-line description tweak might save a future reader some confusion.

(Still doing a manual test pass — will follow up after.)

/>
<Route path="/content-gating" render={ () => <ContentGating { ...props } /> } />
<Route path="/payment" render={ () => <Payment { ...props } /> } />
<Route path="/campaign" render={ () => <Campaign { ...props } /> } />
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.

💡 Suggestion — With auto-enable gone, api_activate_reader_activation no longer re-asserts enabled = true, and these routes (/campaign, /complete) render unconditionally — they don't check config.enabled/chooserOpen. So a site with Audience Management disabled that lands directly on #/campaign or #/complete could publish a campaign while RAS stays disabled. Very unlikely in the normal flow, but the old code was defensively idempotent here. Might be worth gating these routes on config.enabled (or re-asserting enabled on activate).

export const PLATFORM_PLUGINS = {
[ NEWSPACK ]: [ 'woocommerce', 'woocommerce-subscriptions', 'newspack-blocks' ],
[ NRH ]: [ 'newspack-blocks' ],
[ OTHER ]: [],
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.

💡 Suggestion — Selecting Other auto-installs nothing here, but Reader_Activation::get_reader_revenue_required_plugins() still always lists newspack-blocks as required. So an "Other" site with newspack-blocks inactive would see a "recommended plugin" on the config page that the chooser never offered to install. Impact is basically nil (newspack-blocks is effectively always active), but the chooser and Setup disagree slightly — either add newspack-blocks to the OTHER set, or a quick comment noting Setup's recommendations are intentionally broader than the chooser's auto-install set.

@@ -0,0 +1,17 @@
import { OPTIONS, PLATFORM_PLUGINS } from './';

describe( 'PlatformSelection mapping', () => {
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.

💡 Suggestion — This only asserts the static OPTIONS/PLATFORM_PLUGINS mappings — none of the component's actual behavior: the save-then-advance flow, the "don't advance if the save failed" guard, the non-blocking installer "Continue" path, or the disable-confirmation modal. For a ~190-line component that's the centerpiece of this feature, a render/interaction test (mocking the save + PluginInstaller.onStatus) would protect the riskiest new logic. Not blocking — the PHP side is nicely covered by contrast. 🙂

$params = $request->get_params();

Donations::set_platform_slug( $params['platform'] );
if ( isset( $params['platform'] ) ) {
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.

💡 Suggestion — Nice defensive guard. One thing to consider: platform isn't marked 'required' => true on this route, so a POST without it now silently returns the current payment data with a 200 and no change. That's fine for the NRH-settings-only path, but a dropped platform param becomes an invisible no-op — might be worth 'required' => true (or splitting the NRH-only update into its own concern).

🔸 Minor, while you're here: the method's docblock still reads @return WP_REST_Response Boolean success, but it actually returns the payment-data array via rest_ensure_response().

* @return bool
*/
public static function is_platform_selected() {
return null !== get_option( self::NEWSPACK_READER_REVENUE_PLATFORM, null );
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.

🔸 Nit — This is the load-bearing first-run detection, and it's coupled to a side effect: get_platform_slug() writes this option during the legacy stripe → wc migration, so just reading the platform on a legacy site flips is_platform_selected() from false to true. It's documented and intentional (migrated sites are treated as "Newspack selected"), so no change needed — just flagging that a read-with-side-effect feeding first-run detection is a touch fragile if get_platform_slug() ever moves earlier in the request lifecycle.

@@ -693,7 +642,7 @@ public function api_update_salesforce_settings( $request ) {
* @return bool
*/
public function api_validate_platform( $value ) {
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.

🔸 Nit — You tightened the validation here nicely (strict in_array). Newer methods in this class use typed signatures/returns (e.g. api_update_checkout_configuration( WP_REST_Request $request ): WP_REST_Response), whereas this and Donations::is_platform_selected() stay untyped. Given the 8.3 target, api_validate_platform( mixed $value ): bool and is_platform_selected(): bool would read a touch more consistently. Totally optional.

Copy link
Copy Markdown
Contributor

@chickenn00dle chickenn00dle left a comment

Choose a reason for hiding this comment

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

Looks great @miguelpeixe!

This is good to ship as is but I left some inline nits from my Claude review session.

One other non-blocking thought is it feels strange to render a warning for optional Audience Management settings:

Image

Maybe we can make this a simple heading instead. Either that or reintroduce the skip button so the publisher can indicate they intentionally plan to ignore that setting so we can remove the warning once all settings are touched. WDYT?

@github-actions github-actions Bot added [Status] Approved Pull request has been approved and removed [Status] Needs Review labels Jun 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Status] Approved Pull request has been approved

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants