Skip to content

enhancement(admin): strip transient query args via removable_query_args filter - #23499

Open
faisalahammad wants to merge 1 commit into
Yoast:trunkfrom
faisalahammad:23498-removable-query-args
Open

enhancement(admin): strip transient query args via removable_query_args filter#23499
faisalahammad wants to merge 1 commit into
Yoast:trunkfrom
faisalahammad:23498-removable-query-args

Conversation

@faisalahammad

Copy link
Copy Markdown
Contributor

Context

Yoast SEO sets 7 URL query args across 5 admin flows. They persisted in the address bar across reloads, embedded in shared links, and re-triggered side effects. WordPress core ships the removable_query_args filter for exactly this (wp_admin_canonical_url() strips registered args after first request), but Yoast never registered against it. Closes #23498.

Summary

This PR can be summarized in the following changelog entry:

  • Registers redirected_from_site_kit, wpseo_tracked_action, wpseo_tracking_nonce, start-myyoast-connection, _wpnonce, install, and from_tools with the WordPress core removable_query_args filter so they get stripped from admin URLs after first load.

Relevant technical choices:

  • New Removable_Query_Args_Integration under src/integrations/admin/ implements the existing Integration_Interface. Gated on Admin_Conditional, registered as a filter callback on removable_query_args, merges Yoast args onto the existing list (does not replace core args).
  • Args are exposed via a public static get_removable_query_args() so future code can reference a single source of truth.
  • Auto-wired into the Symfony DI container via the existing integration tag (no new DI config needed beyond the class file).
  • The existing JS hand-roll at packages/js/src/integrations-page/myyoast-connection/myyoast-integration.js:421 is kept untouched as defensive belt-and-suspenders.
  • Arg list obtained by grep over src/ and packages/js/src/ for each of from_tools, redirected_from_site_kit, wpseo_tracked_action, wpseo_tracking_nonce, start-myyoast-connection, _wpnonce, install.

Test instructions

Test instructions for the acceptance test before the PR gets merged

This PR can be acceptance tested by following these steps:

  1. Activate Yoast SEO on a WordPress site.
  2. Browser-test each of the 7 args using the procedure in docs/workflows/test-23498-removable-query-args.md (from_tools, start-myyoast-connection + _wpnonce, install, plus the dashboard/tracking args).
  3. For each: trigger the arg, then confirm the URL bar drops the arg after the first response renders.

Relevant test scenarios

  • Changes should be tested with the browser console open
  • Changes should be tested on different posts/pages/taxonomies/custom post types/custom taxonomies
  • Changes should be tested on different editors (Default Block/Gutenberg/Classic/Elementor/other)
  • Changes should be tested on different browsers
  • Changes should be tested on multisite

Reasoning for checked items: the change is admin-only, observable in the browser address bar; cleared cache + dev console sufficient to verify.

Test instructions for QA when the code is in the RC

  • QA should use the same steps as above.

This PR is user-facing (admin URL behaviour). QA can test this PR by following these steps:

  1. Same as acceptance steps above.
  2. Pay extra attention to the install=true caveat: refreshing mid-flow will now lose the dialog, which matches the issue author's stated product call.

Impact check

This PR affects the following parts of the plugin, which may require extra testing:

  • Admin URL canonicalization across all 5 downstream flows.

Other environments

  • This PR also affects Shopify. I have added a changelog entry starting with [shopify-seo], added test instructions for Shopify and attached the Shopify label to this PR.
  • This PR also affects Yoast SEO for Google Docs. I have added a changelog entry starting with [yoast-doc-extension], added test instructions for Yoast SEO for Google Docs and attached the Google Docs Add-on label to this PR.

Documentation

  • I have written documentation for this change. For example, comments in the Relevant technical choices, comments in the code, documentation on Confluence / shared Google Drive / Yoast developer portal, or other.

Reasoning: per-page testing steps added under docs/workflows/test-23498-removable-query-args.md.

Quality assurance

  • I have tested this code to the best of my abilities.
  • During testing, I had activated all plugins that Yoast SEO provides integrations for.
  • I have added unit tests to verify the code works as intended.
  • If any part of the code is behind a feature flag, my test instructions also cover cases where the feature flag is switched off.
  • I have written this PR in accordance with my team's definition of done.
  • I have checked that the base branch is correctly set.
  • I have run grunt build:images and committed the results, if my PR introduces or edits images or SVGs.

Reasoning on unchecked: no image/SVG touched in this PR. Integration partner plugins (Site Kit for redirected_from_site_kit, MyYoast premium for start-myyoast-connection) were not installed in the local smoke environment; manual browser verification covered the 5 free-plugin-triggerable args.

Fixes #23498

faisalahammad added a commit to faisalahammad/wordpress-seo that referenced this pull request Jul 25, 2026
- Use Monkey\Filters\expectAdded for the removable_query_args filter
  registration test, matching add_filter() in the source.
- Remove test_filter_integration: Brain\Monkey does not actually
  register the callback under apply_filters, so the test could not
  observe real filter behaviour.

CI fix for Yoast#23499.
faisalahammad added a commit to faisalahammad/wordpress-seo that referenced this pull request Jul 26, 2026
…estamp

The existing matcher captured \time() at mock setup, then compared
against a fresh \time() at source run. Cross-second boundaries produced
'expected 1, called 0' failures on CI. The hook name string is the
meaningful contract; the exact timestamp can drift by a second with no
behavioural impact.

Refs Yoast#23499
@faisalahammad
faisalahammad force-pushed the 23498-removable-query-args branch from f7ba860 to 893ef2d Compare July 26, 2026 01:30
…gs filter

Registers `redirected_from_site_kit`, `wpseo_tracked_action`,
`wpseo_tracking_nonce`, `start-myyoast-connection`, `_wpnonce`, `install`,
and `from_tools` with the WordPress core `removable_query_args` filter so
they get stripped from admin URLs after first load.

- New `Removable_Query_Args_Integration` under `src/integrations/admin/`
  implementing the existing `Integration_Interface`. Gated on
  `Admin_Conditional`, registered as a filter callback, merges Yoast args
  onto the existing list.
- Args exposed via a `public static get_removable_query_args()` so future
  code can reference a single source of truth.
- Auto-wired into the Symfony DI container via the existing integration
  tag (no new DI config needed).
- The existing JS strip at
  `packages/js/src/integrations-page/myyoast-connection/myyoast-integration.js:421`
  is kept as defensive belt-and-suspenders.
- Flaky-test fix in `Activation_Cleanup_Integration_Test`: matcher uses
  `Mockery::type('int')` instead of capturing `\time()` at mock setup.
  Cross-second boundaries caused CI failures on PHP 8.0.
- Flaky-test fix in `Introductions_Integration_Test`: same `\time()`
  cross-second-boundary pattern replaced with `Mockery::on()` for the
  `seen_on` timestamp value.

Fixes Yoast#23498
@faisalahammad
faisalahammad force-pushed the 23498-removable-query-args branch from 893ef2d to 664e44b Compare July 26, 2026 01:57
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.

Use removable_query_args instead of standard argument passing when appropriate

2 participants