Skip to content

Commit 2c59a33

Browse files
committed
Add contextual banners for WooCommerce Shipping & Tax
Enhance the NUX (New User Experience) system by adding contextual banners that show different content based on: - Store country (US vs non-US) - Whether the WooCommerce Shipping plugin is active This creates a more personalized onboarding flow by: 1. Adding a new option flag for tracking contextual banner state 2. Improving the banner display logic with prioritized checks 3. Creating three different contextual banner types 4. Ensuring proper transition between traditional and contextual banners The change maintains backward compatibility while providing more targeted guidance.
1 parent d9a4742 commit 2c59a33

File tree

1 file changed

+139
-18
lines changed

1 file changed

+139
-18
lines changed

classes/class-wc-connect-nux.php

Lines changed: 139 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ class WC_Connect_Nux {
1616
* Option name for dismissing success banner
1717
* after the JP connection flow
1818
*/
19-
const SHOULD_SHOW_AFTER_CXN_BANNER = 'should_display_nux_after_jp_cxn_banner';
19+
const SHOULD_SHOW_AFTER_CXN_BANNER = 'should_display_nux_after_jp_cxn_banner';
20+
const SHOULD_SHOW_CONTEXTUAL_BANNER = 'should_display_nux_contextual_banner';
2021

2122
/**
2223
* @var WC_Connect_Tracks
@@ -241,23 +242,48 @@ public static function get_banner_type_to_display( $status = array() ) {
241242
return 'before_jetpack_connection';
242243
case self::JETPACK_CONNECTED:
243244
case self::JETPACK_OFFLINE_MODE:
244-
// Has the user just gone through our NUX connection flow?
245+
// Priority 1: Standard "after connection" banner (if pending from NUX flow).
246+
// This banner also handles initial TOS acceptance if coming from the NUX connection flow.
245247
if ( isset( $status['should_display_after_cxn_banner'] ) && $status['should_display_after_cxn_banner'] ) {
246248
return 'after_jetpack_connection';
247249
}
248250

249-
// Has the user already accepted our TOS? Then do nothing.
250-
// Note: TOS is accepted during the after_connection banner
251-
if (
252-
isset( $status['tos_accepted'] )
253-
&& ! $status['tos_accepted']
254-
&& isset( $status['can_accept_tos'] )
255-
&& $status['can_accept_tos']
256-
) {
251+
// Priority 2: TOS acceptance banner (if Jetpack connected, but TOS not yet accepted,
252+
// and the standard "after connection" banner is not pending).
253+
if ( isset( $status['tos_accepted'] ) && ! $status['tos_accepted'] &&
254+
isset( $status['can_accept_tos'] ) && $status['can_accept_tos'] ) {
257255
return 'tos_only_banner';
258256
}
259257

260-
return false;
258+
// For existing users: if TOS accepted, after_cxn_banner done, but contextual_banner flag not yet set, set it now.
259+
if ( isset( $status['tos_accepted'] ) && $status['tos_accepted'] &&
260+
( ! isset( $status['should_display_after_cxn_banner'] ) || ! $status['should_display_after_cxn_banner'] ) &&
261+
( ! isset( $status['should_display_contextual_banner'] ) || ! $status['should_display_contextual_banner'] )
262+
) {
263+
// This user is eligible for contextual banners but the flag isn't set. Set it now.
264+
WC_Connect_Options::update_option( self::SHOULD_SHOW_CONTEXTUAL_BANNER, true );
265+
// Update the status for the current execution path, so Priority 3 check below can pick it up.
266+
$status['should_display_contextual_banner'] = true;
267+
}
268+
269+
// Priority 3: Contextual banners (if standard "after connection" is done or was not applicable,
270+
// TOS is accepted, and the contextual flag is set - either previously or by the block above).
271+
if ( isset( $status['should_display_contextual_banner'] ) && $status['should_display_contextual_banner'] ) {
272+
// Determine which specific contextual banner to show.
273+
$is_us_store = ( isset( $status['store_country'] ) && 'US' === $status['store_country'] );
274+
275+
if ( $is_us_store ) {
276+
if ( isset( $status['is_wcs_shipping_plugin_active'] ) && ! $status['is_wcs_shipping_plugin_active'] ) {
277+
return 'after_cxn_us_no_wcs_plugin';
278+
} else {
279+
return 'after_cxn_us_with_wcs_plugin';
280+
}
281+
} else {
282+
return 'after_cxn_non_us';
283+
}
284+
}
285+
286+
return false; // All NUX banners handled or no NUX banner needed for this state.
261287
default:
262288
return false;
263289
}
@@ -372,12 +398,22 @@ public function set_up_nux_notices() {
372398
// If this is the case, the admin can connect the site on their own, and should be able to use WCS as ususal
373399
$jetpack_install_status = $this->get_jetpack_install_status();
374400

401+
// Ensure is_plugin_active() is available for WCS check
402+
if ( ! function_exists( 'is_plugin_active' ) ) {
403+
include_once ABSPATH . 'wp-admin/includes/plugin.php';
404+
}
405+
$is_wcs_shipping_plugin_active = is_plugin_active( 'woocommerce-shipping/woocommerce-shipping.php' );
406+
$store_country = WC()->countries->get_base_country();
407+
375408
$banner_to_display = self::get_banner_type_to_display(
376409
array(
377-
'jetpack_connection_status' => $jetpack_install_status,
378-
'tos_accepted' => WC_Connect_Options::get_option( 'tos_accepted' ),
379-
'can_accept_tos' => WC_Connect_Jetpack::is_current_user_connection_owner() || WC_Connect_Jetpack::is_offline_mode(),
380-
'should_display_after_cxn_banner' => WC_Connect_Options::get_option( self::SHOULD_SHOW_AFTER_CXN_BANNER ),
410+
'jetpack_connection_status' => $jetpack_install_status,
411+
'tos_accepted' => WC_Connect_Options::get_option( 'tos_accepted' ),
412+
'can_accept_tos' => WC_Connect_Jetpack::is_current_user_connection_owner() || WC_Connect_Jetpack::is_offline_mode(),
413+
'should_display_after_cxn_banner' => WC_Connect_Options::get_option( self::SHOULD_SHOW_AFTER_CXN_BANNER ),
414+
'should_display_contextual_banner' => WC_Connect_Options::get_option( self::SHOULD_SHOW_CONTEXTUAL_BANNER ),
415+
'store_country' => $store_country,
416+
'is_wcs_shipping_plugin_active' => $is_wcs_shipping_plugin_active,
381417
)
382418
);
383419

@@ -391,13 +427,25 @@ public function set_up_nux_notices() {
391427
wp_enqueue_style( 'wc_connect_banner' );
392428
add_action( 'admin_notices', array( $this, 'show_banner_before_connection' ), 9 );
393429
break;
430+
case 'after_jetpack_connection':
431+
wp_enqueue_style( 'wc_connect_banner' );
432+
add_action( 'admin_notices', array( $this, 'show_banner_after_connection' ) );
433+
break;
394434
case 'tos_only_banner':
395435
wp_enqueue_style( 'wc_connect_banner' );
396436
add_action( 'admin_notices', array( $this, 'show_tos_banner' ) );
397437
break;
398-
case 'after_jetpack_connection':
438+
case 'after_cxn_us_no_wcs_plugin':
439+
case 'after_cxn_us_with_wcs_plugin':
440+
case 'after_cxn_non_us':
399441
wp_enqueue_style( 'wc_connect_banner' );
400-
add_action( 'admin_notices', array( $this, 'show_banner_after_connection' ) );
442+
// Using a closure to correctly pass the argument to the new handler method.
443+
add_action(
444+
'admin_notices',
445+
function () use ( $banner_to_display ) {
446+
$this->show_contextual_after_connection_banner( $banner_to_display );
447+
}
448+
);
401449
break;
402450
}
403451

@@ -452,8 +500,10 @@ public function show_banner_after_connection() {
452500

453501
// Did the user just dismiss?
454502
if ( isset( $_GET['wcs-nux-notice'] ) && 'dismiss' === $_GET['wcs-nux-notice'] ) {
455-
// No longer need to keep track of whether the before connection banner was displayed.
503+
// Delete the flag for this banner
456504
WC_Connect_Options::delete_option( self::SHOULD_SHOW_AFTER_CXN_BANNER );
505+
// Set the flag for the next contextual banner
506+
WC_Connect_Options::update_option( self::SHOULD_SHOW_CONTEXTUAL_BANNER, true );
457507
wp_safe_redirect( remove_query_arg( 'wcs-nux-notice' ) );
458508
exit;
459509
}
@@ -487,6 +537,73 @@ public function show_banner_after_connection() {
487537
);
488538
}
489539

540+
public function show_contextual_after_connection_banner( $banner_type ) {
541+
$screen = get_current_screen();
542+
543+
// This specific banner should only appear on the plugins page.
544+
if ( ! $screen || 'plugins' !== $screen->base ) {
545+
return;
546+
}
547+
548+
// Still respect the store locale check.
549+
if ( ! $this->should_display_nux_notice_for_current_store_locale() ) {
550+
return;
551+
}
552+
553+
// Did the user just dismiss?
554+
if ( isset( $_GET['wcs-nux-notice'] ) && 'dismiss' === $_GET['wcs-nux-notice'] ) {
555+
// Delete the flag for this contextual banner
556+
WC_Connect_Options::delete_option( self::SHOULD_SHOW_CONTEXTUAL_BANNER );
557+
wp_safe_redirect( remove_query_arg( 'wcs-nux-notice' ) );
558+
exit;
559+
}
560+
561+
// By going through the connection process, the user has accepted our TOS
562+
WC_Connect_Options::update_option( 'tos_accepted', true );
563+
564+
// Using a generic tracks event, can be made more specific if needed.
565+
$this->tracks->opted_in( 'contextual_connection_banner_viewed' );
566+
567+
$banner_title = '';
568+
$banner_description = '';
569+
570+
switch ( $banner_type ) {
571+
case 'after_cxn_us_no_wcs_plugin':
572+
$banner_title = __( 'US Store: WooCommerce Shipping Plugin Not Active - Title', 'woocommerce-services' );
573+
$banner_description = __( 'US Store: WooCommerce Shipping Plugin Not Active - Description.', 'woocommerce-services' );
574+
break;
575+
case 'after_cxn_us_with_wcs_plugin':
576+
$banner_title = __( 'US Store: WooCommerce Shipping Plugin Active - Title', 'woocommerce-services' );
577+
$banner_description = __( 'US Store: WooCommerce Shipping Plugin Active - Description.', 'woocommerce-services' );
578+
break;
579+
case 'after_cxn_non_us':
580+
$banner_title = __( 'Non-US Store - Title', 'woocommerce-services' );
581+
$banner_description = __( 'Non-US Store - Description.', 'woocommerce-services' );
582+
break;
583+
default:
584+
// Fallback for an unknown banner type, though this shouldn't be reached with current logic.
585+
return;
586+
}
587+
588+
$this->show_nux_banner(
589+
array(
590+
'title' => $banner_title,
591+
'description' => esc_html( $banner_description ),
592+
'button_text' => __( 'Got it, thanks!', 'woocommerce-services' ),
593+
'button_link' => add_query_arg(
594+
array(
595+
'wcs-nux-notice' => 'dismiss',
596+
)
597+
),
598+
'image_url' => plugins_url(
599+
'images/wcs-notice.png',
600+
__DIR__
601+
),
602+
'should_show_terms' => false,
603+
)
604+
);
605+
}
606+
490607
public function show_tos_banner() {
491608
if ( ! $this->should_display_nux_notice_for_current_store_locale() ) {
492609
return;
@@ -498,6 +615,8 @@ public function show_tos_banner() {
498615

499616
if ( isset( $_GET['wcs-nux-tos'] ) && 'accept' === $_GET['wcs-nux-tos'] ) {
500617
WC_Connect_Options::update_option( 'tos_accepted', true );
618+
// Signal that the contextual banner can now be shown
619+
WC_Connect_Options::update_option( self::SHOULD_SHOW_CONTEXTUAL_BANNER, true );
501620

502621
$this->tracks->opted_in( 'tos_banner' );
503622

@@ -625,6 +744,8 @@ public function register_woocommerce_services_jetpack() {
625744
// Make sure we always display the after-connection banner
626745
// after the before_connection button is clicked
627746
WC_Connect_Options::update_option( self::SHOULD_SHOW_AFTER_CXN_BANNER, true );
747+
// Ensure the contextual banner flag is not set prematurely
748+
WC_Connect_Options::delete_option( self::SHOULD_SHOW_CONTEXTUAL_BANNER );
628749

629750
WC_Connect_Jetpack::connect_site( $redirect_url );
630751
}

0 commit comments

Comments
 (0)