Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save xlplugins/addbd2f238a7b8843a40ac599697c596 to your computer and use it in GitHub Desktop.
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."
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