fix(affiliate): persist referral code through SPA checkout and process after save
This commit is contained in:
@@ -5,6 +5,48 @@ import './styles/fonts.css';
|
|||||||
import './styles/theme.css';
|
import './styles/theme.css';
|
||||||
import App from './App';
|
import App from './App';
|
||||||
|
|
||||||
|
// Capture referral code from URL on app load
|
||||||
|
// This ensures referral tracking works even for block/AJAX checkout flows
|
||||||
|
(function captureReferralCode() {
|
||||||
|
const params = new URLSearchParams(window.location.search);
|
||||||
|
const ref = params.get('ref');
|
||||||
|
console.log('[WooNooW] captureReferralCode - URL search:', window.location.search, ', ref:', ref);
|
||||||
|
|
||||||
|
if (ref && ref.trim() !== '') {
|
||||||
|
// Store in localStorage as backup
|
||||||
|
try {
|
||||||
|
localStorage.setItem('woonoow_ref', ref);
|
||||||
|
console.log('[WooNooW] Stored ref in localStorage:', ref);
|
||||||
|
} catch (e) {
|
||||||
|
// localStorage may be blocked
|
||||||
|
console.log('[WooNooW] localStorage blocked:', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also set cookie for PHP backend to read
|
||||||
|
// Cookie expires in 30 days, path is root
|
||||||
|
const expires = new Date();
|
||||||
|
expires.setDate(expires.getDate() + 30);
|
||||||
|
const cookieStr = `woonoow_ref=${encodeURIComponent(ref)}; expires=${expires.toUTCString()}; path=/; SameSite=Lax`;
|
||||||
|
document.cookie = cookieStr;
|
||||||
|
console.log('[WooNooW] Set cookie:', cookieStr);
|
||||||
|
} else {
|
||||||
|
// Check if ref exists in localStorage from previous visit
|
||||||
|
try {
|
||||||
|
const storedRef = localStorage.getItem('woonoow_ref');
|
||||||
|
if (storedRef) {
|
||||||
|
console.log('[WooNooW] Found stored ref in localStorage:', storedRef);
|
||||||
|
// Re-set the cookie from localStorage
|
||||||
|
const expires = new Date();
|
||||||
|
expires.setDate(expires.getDate() + 30);
|
||||||
|
document.cookie = `woonoow_ref=${encodeURIComponent(storedRef)}; expires=${expires.toUTCString()}; path=/; SameSite=Lax`;
|
||||||
|
console.log('[WooNooW] Re-set cookie from localStorage:', storedRef);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
console.log('[WooNooW] Could not read localStorage:', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
const el = document.getElementById('woonoow-customer-app');
|
const el = document.getElementById('woonoow-customer-app');
|
||||||
if (el) {
|
if (el) {
|
||||||
createRoot(el).render(
|
createRoot(el).render(
|
||||||
|
|||||||
@@ -599,6 +599,18 @@ export default function Checkout() {
|
|||||||
setIsProcessing(true);
|
setIsProcessing(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const referralCode = (() => {
|
||||||
|
try {
|
||||||
|
const stored = localStorage.getItem('woonoow_ref')?.trim();
|
||||||
|
if (stored) return stored;
|
||||||
|
} catch {
|
||||||
|
// Ignore storage access errors.
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = document.cookie.match(/(?:^|;\s*)woonoow_ref=([^;]+)/);
|
||||||
|
return match ? decodeURIComponent(match[1]).trim() : '';
|
||||||
|
})();
|
||||||
|
|
||||||
// Prepare order data
|
// Prepare order data
|
||||||
const orderData = {
|
const orderData = {
|
||||||
items: cart.items.map(item => ({
|
items: cart.items.map(item => ({
|
||||||
@@ -652,6 +664,7 @@ export default function Checkout() {
|
|||||||
custom_fields: customFieldData,
|
custom_fields: customFieldData,
|
||||||
// CAPTCHA token for security validation
|
// CAPTCHA token for security validation
|
||||||
captcha_token: captchaToken,
|
captcha_token: captchaToken,
|
||||||
|
referral_code: referralCode || undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Submit order
|
// Submit order
|
||||||
@@ -670,8 +683,16 @@ export default function Checkout() {
|
|||||||
// If user was logged in during this request (guest auto-register),
|
// If user was logged in during this request (guest auto-register),
|
||||||
// we need a full page reload to recognize the auth cookie
|
// we need a full page reload to recognize the auth cookie
|
||||||
if (data.user_logged_in) {
|
if (data.user_logged_in) {
|
||||||
|
// Get basePath from window
|
||||||
|
const basePath = (window as any).woonoowCustomer?.basePath ?? '/store';
|
||||||
|
|
||||||
|
// Ensure thankYouUrl starts with / if basePath doesn't end with /
|
||||||
|
const sep = basePath.endsWith('/') || thankYouUrl.startsWith('/') ? '' : '/';
|
||||||
|
const prefix = thankYouUrl.startsWith('/') && basePath.endsWith('/') ? basePath.slice(0, -1) : basePath;
|
||||||
|
|
||||||
// Full page reload so browser recognizes the new auth cookie
|
// Full page reload so browser recognizes the new auth cookie
|
||||||
window.location.href = thankYouUrl;
|
const path = thankYouUrl.startsWith('/') ? thankYouUrl.slice(1) : thankYouUrl;
|
||||||
|
window.location.href = `${prefix}${sep}${path}`;
|
||||||
} else {
|
} else {
|
||||||
// Already logged in or no login happened - SPA navigate is fine
|
// Already logged in or no login happened - SPA navigate is fine
|
||||||
navigate(thankYouUrl, { replace: true });
|
navigate(thankYouUrl, { replace: true });
|
||||||
|
|||||||
@@ -329,6 +329,11 @@ class CheckoutController
|
|||||||
return ['error' => $order->get_error_message()];
|
return ['error' => $order->get_error_message()];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!empty($payload['referral_code'])) {
|
||||||
|
$order->update_meta_data('_woonoow_referral_code', $payload['referral_code']);
|
||||||
|
$_COOKIE['woonoow_ref'] = $payload['referral_code'];
|
||||||
|
}
|
||||||
|
|
||||||
// Track if user was logged in during this request (for frontend page reload)
|
// Track if user was logged in during this request (for frontend page reload)
|
||||||
$user_logged_in = false;
|
$user_logged_in = false;
|
||||||
|
|
||||||
@@ -516,6 +521,11 @@ class CheckoutController
|
|||||||
|
|
||||||
$order->save();
|
$order->save();
|
||||||
|
|
||||||
|
// wc_create_order() fires woocommerce_new_order before SPA checkout line
|
||||||
|
// items exist. Fire the processed hook after saving so integrations that
|
||||||
|
// calculate from order items, like affiliate tracking, see a complete order.
|
||||||
|
do_action('woocommerce_checkout_order_processed', $order->get_id(), $payload, $order);
|
||||||
|
|
||||||
if (!headers_sent()) {
|
if (!headers_sent()) {
|
||||||
header('Server-Timing: app;dur=' . round((microtime(true) - $__t0) * 1000, 1));
|
header('Server-Timing: app;dur=' . round((microtime(true) - $__t0) * 1000, 1));
|
||||||
}
|
}
|
||||||
@@ -842,6 +852,7 @@ class CheckoutController
|
|||||||
'shipping_title' => isset($json['shipping_title']) ? sanitize_text_field($json['shipping_title']) : null,
|
'shipping_title' => isset($json['shipping_title']) ? sanitize_text_field($json['shipping_title']) : null,
|
||||||
'custom_fields' => $custom_fields,
|
'custom_fields' => $custom_fields,
|
||||||
'customer_note' => isset($json['customer_note']) ? sanitize_textarea_field($json['customer_note']) : '',
|
'customer_note' => isset($json['customer_note']) ? sanitize_textarea_field($json['customer_note']) : '',
|
||||||
|
'referral_code' => isset($json['referral_code']) ? sanitize_text_field($json['referral_code']) : '',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user