Skip to content

Implement Golinks concept for generalisable redirects to SK screens #11849

@benbowler

Description

@benbowler

Feature Description

All links in the email template should point to a redirection proxy that maps a key to a dashboard (or documentation URL). This allows us to change destination URLs for elements of the plugin in future without breaking links in already delivered emails.

Specifically, the accept invite link/manage account links within the emails should conditionally redirect to the view-only splash page, with redirect_url set (defined in #11890) to open the email reporting panel after splash page dismissal. Otherwise, it should redirect directly to the dashboard to open the panel.


Do not alter or remove anything below. The following sections will be managed by moderators only.

Acceptance criteria

  • A user clicking a golink URL (index.php?action=googlesitekit_go&to={key}) is redirected to the registered destination via wp_safe_redirect()
  • A user clicking an invalid or unregistered golink receives a wp_die() 404 response with contextual links (dashboard or splash screen based on user capabilities)
  • Email report links (dashboard CTA, unsubscribe, email settings, "View more in dashboard", page-entity links) use golink URLs; external documentation links remain direct
  • All other email templates (invitation-email, error-email and subscription-confirmation templates) use golink URLs for all plugin links

Implementation Brief

Backend (PHP) - Golinks core

  • Create file includes/Core/Golinks/Golink_Handler_Interface.php:

    • Interface with single method handle( Context $context ): string|WP_Error
    • Receives the Context instance so consumers don't need to be constructed with it (provides Input and admin URL building)
    • Handler is responsible for constructing the full redirect URL, including reading and forwarding any parameters it cares about
  • Create file includes/Core/Golinks/Golinks.php:

    • Constructor accepts Context instance
    • $handlers array maps string keys to Golink_Handler_Interface instances
    • register() hooks into admin_action_googlesitekit_go
    • register_handler( $key, Golink_Handler_Interface $handler ) registers a handler for a key; throws/dies if a handler for that key is already registered
    • get_url($key) returns golink URL for registered key (returns null for unregistered)
    • handle_go():
      • Extract to via $this->context->input()->filter(INPUT_GET, ...)
      • If key not found in $handlers, call wp_die() with a 404 response code and a message containing contextual links: link to the Site Kit dashboard if the user can view the dashboard, otherwise link to the splash/setup screen
      • Call $handler->handle( $this->context ) to get destination URL
      • If result is WP_Error, call wp_die() with the error message and appropriate status code
      • wp_safe_redirect($url) and exit
  • Update file includes/Plugin.php:

    • Instantiate Golinks with $this->context
    • Call $golinks->register()
    • Register dashboard handler: $golinks->register_handler( 'dashboard', new Dashboard_Golink_Handler() ) — handler reads permaLink from $context->input() and appends it to the dashboard URL
    • Pass $golinks to Email_Reporting constructor

Backend (PHP) - Email report template data

  • Update file includes/Core/Email_Reporting/Email_Reporting.php:

    • Add Golinks constructor param, store as $this->golinks
    • In register(), register the manage-subscription-email-reporting golink handler: $this->golinks->register_handler( 'manage-subscription-email-reporting', new Email_Reporting_Golink_Handler() ) — handler builds the dashboard URL with ['panel' => 'email-reporting'] via $context->admin_url()
    • Pass $golinks to Email_Template_Formatter and Email_Template_Renderer_Factory constructors
  • Update file includes/Core/Email_Reporting/Email_Template_Formatter.php:

    • Add Golinks constructor param
    • In prepare_template_data() (weekly/monthly report emails):
      • Replace admin_url() calls with $this->golinks->get_url('dashboard') for primary_call_to_action.url
      • Replace admin_url() calls with $this->golinks->get_url('manage-subscription-email-reporting') for footer.unsubscribe_url and footer.links[0].url (Manage subscription)
    • In prepare_simple_email_data() (invitation/subscription-confirmation emails):
      • Set $dashboard_url to $this->golinks->get_url('dashboard')
      • Set $email_settings_url to $this->golinks->get_url('manage-subscription-email-reporting')
      • Populate footer.unsubscribe_url and footer.links array (Manage subscription, Privacy Policy, Help center)
      • Use $dashboard_url for primary_call_to_action.url
    • In build_template_payload(), pass $this->golinks to Sections_Map constructor
  • Update file includes/Core/Email_Reporting/Sections_Map.php:

    • Add Golinks constructor param
    • Add get_dashboard_url() helper that returns $this->golinks->get_url('dashboard')
    • Replace all 5 hardcoded $this->context->admin_url('dashboard') calls in section definitions with $this->get_dashboard_url() - this feeds $section['dashboard_url'] used by:
      • templates/email-report/parts/section-page-metrics.php for per-page permaLink deep links and "View more in dashboard" CTAs
      • templates/email-report/parts/section-metrics.php for "View more in dashboard" CTA
      • templates/email-report/parts/section-conversions.php for "View more in dashboard" CTA
  • Update file includes/Core/Email_Reporting/Email_Template_Renderer_Factory.php:

    • Add Golinks constructor param
    • Pass $this->golinks to Sections_Map in create()

Backend (PHP) - Email reporting panel param migration

  • Update file includes/Core/Email_Reporting/Email_Reporting_Pointer.php:
    • Change CTA link from array('email-reporting-panel' => 1) to array('panel' => 'email-reporting')

Frontend (JS)

  • Update file assets/js/hooks/useOpenEmailReportingSelectionPanelEffect.js:
    • Replace useQueryArg('email-reporting-panel') with useQueryArg('panel')
    • Check panel === 'email-reporting' instead of emailReportingPanelOpen !== undefined
    • Clear with setPanel(undefined) instead of setEmailReportingPanelOpen(undefined)

Test Coverage

  • PHPUnit: tests/phpunit/integration/Core/Golinks/GolinksTest.php:
    • register_handler registers new Golink.
    • get_url returns correct format, returns null for unregistered key
    • handle_go redirects to handler destination, dies with 404 for invalid link
    • handle_go returns wp_die() with error when handler returns WP_Error
    • register_handler throws/dies when registering a duplicate key

QA Brief

  • Setup Site Kit
  • Paste this path to the root website URL: /wp-admin/index.php?action=googlesitekit_go&to=dashboard
  • Expect redirect to Site Kit dashboard
  • Add this path /wp-admin/index.php?action=googlesitekit_go&to=manage-subscription-email-reporting
  • Expect redirect to dashboard with email reporting panel open

  • View only user should have same results as above when including these paths

  • Login as a second admin
  • Paste this path /wp-admin/index.php?action=googlesitekit_go&to=manage-subscription-email-reporting
  • You should land on splash screen, and after signing in/dismissing it if going with view only dashboard you should land on Site Kit dashboard with email reporting panel open
    • Otherwise, if splash screen has been passed, above paths will behave same as for main admin after SK setup

  • Invalid URL
    • As main admin, or secondary admin, paste this path /wp-admin/index.php?action=googlesitekit_go&to=invalid-key you should land on 404 page with a link to the site kit dashboard

  • Subscribe to email reporting and trigger an email - Existing links should still work - manage/unsubscribe should lead to dashboard with email reporting panel open, etc

Changelog entry

  • Add support for stable deep links to dashboard and email subscription management.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P0High priorityTeam SIssues for Squad 1Type: EnhancementImprovement of an existing feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions