Last active
July 10, 2025 12:59
-
-
Save xlplugins/addbd2f238a7b8843a40ac599697c596 to your computer and use it in GitHub Desktop.
"Automatically reload or redirect the FunnelKit checkout page if a product in the cart belongs to a different FunnelKit checkout funnel."
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class WFACP_Checkout_Mismatch_Handler { | |
private $logger; | |
public function __construct() { | |
$this->logger = wc_get_logger(); | |
add_filter( 'woocommerce_add_cart_item', [ $this, 'add_cart_item_checkout_page_id' ], 10 ); | |
add_filter( 'woocommerce_update_order_review_fragments', [ $this, 'check_checkout_page_id_fragment' ] ); | |
add_action( 'woocommerce_after_checkout_validation', [ $this, 'validate_checkout_page_match' ], 10, 2 ); | |
add_action( 'wp_footer', [ $this, 'footer_script' ], 99 ); | |
add_action( 'rest_api_init', [ $this, 'register_ajax_point' ] ); | |
} | |
public function add_cart_item_checkout_page_id( $cart_item ) { | |
if ( isset( $cart_item['_wfacp_product'] ) ) { | |
$checkout_id = WFACP_Common::get_id(); | |
$cart_item['_wfacp_checkout_page_id'] = $checkout_id; | |
$this->logger->info( "Add to cart: checkout page ID = {$checkout_id}", [ 'source' => 'wfacp' ] ); | |
} | |
return $cart_item; | |
} | |
public function check_checkout_page_id_fragment( $fragments ) { | |
if ( ! is_checkout() || ! wp_doing_ajax() || did_action( 'wfacp_after_template_found' ) === 0 ) { | |
return $fragments; | |
} | |
$current_checkout_id = WFACP_Common::get_id(); | |
$this->logger->info( "Fragment check: current checkout ID = {$current_checkout_id}", [ 'source' => 'wfacp' ] ); | |
foreach ( WC()->cart->get_cart_contents() as $cart_item ) { | |
if ( isset( $cart_item['_wfacp_checkout_page_id'] ) && $cart_item['_wfacp_checkout_page_id'] != $current_checkout_id ) { | |
$this->logger->warning( "Fragment mismatch: Cart item checkout ID {$cart_item['_wfacp_checkout_page_id']} != current {$current_checkout_id}", [ 'source' => 'wfacp' ] ); | |
$fragments['wfacp_checkout_miss_match'] = 'miss_match_checkout'; | |
break; | |
} | |
} | |
return $fragments; | |
} | |
public function validate_checkout_page_match( &$data, &$errors ) { | |
if ( ! wp_doing_ajax() || did_action( 'wfacp_after_template_found' ) === 0 ) { | |
return; | |
} | |
$current_checkout_id = WFACP_Common::get_id(); | |
$this->logger->info( "Checkout validation: current checkout ID = {$current_checkout_id}", [ 'source' => 'wfacp' ] ); | |
foreach ( WC()->cart->get_cart_contents() as $cart_item ) { | |
if ( isset( $cart_item['_wfacp_checkout_page_id'] ) && $cart_item['_wfacp_checkout_page_id'] != $current_checkout_id ) { | |
$this->logger->error( "Validation failed: Cart item checkout ID {$cart_item['_wfacp_checkout_page_id']} != current {$current_checkout_id}", [ 'source' => 'wfacp' ] ); | |
$errors->add( 'wfacp_cart_items', __( '', 'woofunnels-aero-checkout' ), [ 'id' => 'wfacp_checkout_miss_match' ] ); | |
return; | |
} | |
} | |
} | |
public function footer_script() { | |
if ( ! is_checkout() ) { | |
return; | |
} | |
$rest_url = esc_url_raw( rest_url( 'wfacp/v1/navigation' ) ); | |
?> | |
<script> | |
(function ($) { | |
function sendTracking(data) { | |
navigator.sendBeacon = navigator.sendBeacon || function (url, payload) { | |
fetch(url, { | |
method: "POST", | |
body: JSON.stringify(payload), | |
headers: { | |
"Content-Type": "application/json" | |
}, | |
keepalive: true | |
}); | |
}; | |
//alert(JSON.stringify(data)); | |
navigator.sendBeacon('<?php echo $rest_url; ?>', data); | |
} | |
$(document).ready(function () { | |
let currentUrl = window.location.href; | |
document.addEventListener('visibilitychange', function () { | |
if (document.visibilityState === 'hidden') { | |
let nextUrl = document.activeElement?.href || ''; | |
sendTracking({ | |
type: 'redirect_start', | |
from: currentUrl, | |
to: nextUrl, | |
timestamp: Date.now(), | |
user_agent: navigator.userAgent, | |
language: navigator.language, | |
platform: navigator.platform | |
}); | |
} | |
}); | |
window.addEventListener('beforeunload', function () { | |
let nextUrl = document.activeElement?.href || ''; | |
sendTracking({ | |
type: 'navigate_away', | |
from: currentUrl, | |
to: nextUrl, | |
timestamp: Date.now(), | |
user_agent: navigator.userAgent, | |
language: navigator.language, | |
platform: navigator.platform | |
}); | |
}); | |
if (performance && performance.navigation && performance.navigation.type === 2) { | |
sendTracking({ | |
type: 'landed_back', | |
current: currentUrl, | |
timestamp: Date.now(), | |
user_agent: navigator.userAgent, | |
language: navigator.language, | |
platform: navigator.platform | |
}); | |
window.location.reload(); | |
} | |
$(document.body).on('checkout_error', function (error_message) { | |
setTimeout(function () { | |
let error_exist = $('li[data-id="wfacp_checkout_miss_match"]'); | |
console.log('error_exist', error_exist); | |
if (error_exist.length > 0) { | |
error_exist.remove(); | |
if ($('.woocommerce-error li').length == 0) { | |
$('.woocommerce-error').remove(); | |
} | |
refresh_page_data($('._wfacp_post_id').val()); | |
} | |
}) | |
console.log('error_message', error_message) | |
}); | |
$(document.body).on('updated_checkout', function (e, data) { | |
if (typeof data == "object" && data.hasOwnProperty('fragments') && data.fragments.hasOwnProperty('wfacp_checkout_miss_match')) { | |
window.location.reload(); | |
} | |
}); | |
}); | |
})(jQuery); | |
</script> | |
<?php | |
} | |
public function register_ajax_point(): void { | |
register_rest_route( 'wfacp/v1', '/navigation', [ | |
'methods' => 'POST', | |
'callback' => [ $this, 'handle_rest_tracking' ], | |
'permission_callback' => '__return_true' | |
] ); | |
} | |
public function handle_rest_tracking( WP_REST_Request $request ) { | |
$data = $request->get_json_params(); | |
$type = isset( $data['type'] ) ? sanitize_text_field( $data['type'] ) : 'unknown'; | |
$from = isset( $data['from'] ) ? esc_url_raw( $data['from'] ) : ''; | |
$to = isset( $data['to'] ) ? esc_url_raw( $data['to'] ) : ''; | |
$current = isset( $data['current'] ) ? esc_url_raw( $data['current'] ) : ''; | |
$ua = isset( $data['user_agent'] ) ? sanitize_text_field( $data['user_agent'] ) : ''; | |
$language = isset( $data['language'] ) ? sanitize_text_field( $data['language'] ) : ''; | |
$platform = isset( $data['platform'] ) ? sanitize_text_field( $data['platform'] ) : ''; | |
$message = strtoupper( $type ) . ' | '; | |
if ( $type === 'navigate_away' ) { | |
$message .= "From: {$from} → To: {$to}"; | |
} elseif ( $type === 'landed_back' ) { | |
$message .= "User landed via BACK on: {$current}"; | |
} elseif ( $type === 'redirect_start' ) { | |
$message .= "Redirection started from: {$from} to {$to}"; | |
} else { | |
$message .= "Unknown event."; | |
} | |
$message .= " | UA: {$ua} | Lang: {$language} | Platform: {$platform}"; | |
$this->logger->info( $message, [ 'source' => 'wfacp' ] ); | |
return rest_ensure_response( [ 'status' => 'logged' ] ); | |
} | |
} | |
new WFACP_Checkout_Mismatch_Handler(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment