- Add WP Media Library integration for product and variation images - Support images array (URLs) conversion to attachment IDs - Add images array to API responses (Admin & Customer SPA) - Implement drag-and-drop sortable images in Admin product form - Add image gallery thumbnails in Customer SPA product page - Initialize WooCommerce session for guest cart operations - Fix product variations and attributes display in Customer SPA - Add variation image field in Admin SPA Changes: - includes/Api/ProductsController.php: Handle images array, add to responses - includes/Frontend/ShopController.php: Add images array for customer SPA - includes/Frontend/CartController.php: Initialize WC session for guests - admin-spa/src/lib/wp-media.ts: Add openWPMediaGallery function - admin-spa/src/routes/Products/partials/tabs/GeneralTab.tsx: WP Media + sortable images - admin-spa/src/routes/Products/partials/tabs/VariationsTab.tsx: Add variation image field - customer-spa/src/pages/Product/index.tsx: Add gallery thumbnails display
5.7 KiB
Fix: Product Page Redirect Issue
Problem
Direct access to product URLs like /product/edukasi-anak redirects to /shop.
Root Cause
WordPress Canonical Redirect
WordPress has a built-in canonical redirect system that redirects "incorrect" URLs to their "canonical" version. When you access /product/edukasi-anak, WordPress doesn't recognize this as a valid WordPress route (because it's a React Router route), so it redirects to the shop page.
How WordPress Canonical Redirect Works
- User visits
/product/edukasi-anak - WordPress checks if this is a valid WordPress route
- WordPress doesn't find a post/page with this URL
- WordPress thinks it's a 404 or incorrect URL
- WordPress redirects to the nearest valid URL (shop page)
This happens before React Router can handle the URL.
Solution
Disable WordPress canonical redirects for SPA routes.
Implementation
File: includes/Frontend/TemplateOverride.php
1. Hook into Redirect Filter
public static function init() {
// ... existing code ...
// Disable canonical redirects for SPA routes
add_filter('redirect_canonical', [__CLASS__, 'disable_canonical_redirect'], 10, 2);
}
2. Add Redirect Handler
/**
* Disable canonical redirects for SPA routes
* This prevents WordPress from redirecting /product/slug URLs
*/
public static function disable_canonical_redirect($redirect_url, $requested_url) {
$settings = get_option('woonoow_customer_spa_settings', []);
$mode = isset($settings['mode']) ? $settings['mode'] : 'disabled';
// Only disable redirects in full SPA mode
if ($mode !== 'full') {
return $redirect_url;
}
// Check if this is a SPA route
$spa_routes = ['/product/', '/cart', '/checkout', '/my-account'];
foreach ($spa_routes as $route) {
if (strpos($requested_url, $route) !== false) {
// This is a SPA route, disable WordPress redirect
return false;
}
}
return $redirect_url;
}
How It Works
The redirect_canonical Filter
WordPress provides the redirect_canonical filter that allows you to control canonical redirects.
Parameters:
$redirect_url- The URL WordPress wants to redirect to$requested_url- The URL the user requested
Return Values:
- Return
$redirect_url- Allow the redirect - Return
false- Disable the redirect - Return different URL - Redirect to that URL instead
Our Logic
- Check if SPA mode is enabled
- Check if the requested URL contains SPA routes (
/product/,/cart, etc.) - If yes, return
falseto disable redirect - If no, return
$redirect_urlto allow normal WordPress behavior
Why This Works
Before Fix
User → /product/edukasi-anak
↓
WordPress: "This isn't a valid route"
↓
WordPress: "Redirect to /shop"
↓
React Router never gets a chance to handle the URL
After Fix
User → /product/edukasi-anak
↓
WordPress: "Should I redirect?"
↓
Our filter: "No, this is a SPA route"
↓
WordPress: "OK, loading template"
↓
React Router: "I'll handle /product/edukasi-anak"
↓
Product page loads correctly
Testing
Test Direct Access
- Open new browser tab
- Go to:
https://woonoow.local/product/edukasi-anak - Should load product page directly
- Should NOT redirect to
/shop
Test Navigation
- Go to
/shop - Click a product
- Should navigate to
/product/slug - Should work correctly
Test Other Routes
/cart- Should work/checkout- Should work/my-account- Should work
Check Console
Open browser console and check for logs:
Product Component - Slug: edukasi-anak
Product Component - Current URL: https://woonoow.local/product/edukasi-anak
Product Query - Starting fetch for slug: edukasi-anak
Product API Response: {...}
Product found: {...}
Additional Notes
SPA Routes Protected
The following routes are protected from canonical redirects:
/product/- Product detail pages/cart- Cart page/checkout- Checkout page/my-account- Account pages
Only in Full SPA Mode
This fix only applies when SPA mode is set to full. In other modes, WordPress canonical redirects work normally.
No Impact on SEO
Disabling canonical redirects for SPA routes doesn't affect SEO because:
- These are client-side routes handled by React
- The actual WordPress product pages still exist
- Search engines see the server-rendered content
- Canonical URLs are still set in meta tags
Alternative Solutions
Option 1: Hash Router (Not Recommended)
Use HashRouter instead of BrowserRouter:
<HashRouter>
{/* routes */}
</HashRouter>
URLs become: https://woonoow.local/#/product/edukasi-anak
Pros:
- No server-side configuration needed
- Works everywhere
Cons:
- Ugly URLs with
# - Poor SEO
- Not modern web standard
Option 2: Custom Rewrite Rules (More Complex)
Add custom WordPress rewrite rules for SPA routes.
Pros:
- More "proper" WordPress way
Cons:
- More complex
- Requires flush_rewrite_rules()
- Can conflict with other plugins
Option 3: Our Solution (Best)
Disable canonical redirects for SPA routes.
Pros:
- ✅ Clean URLs
- ✅ Simple implementation
- ✅ No conflicts
- ✅ Easy to maintain
Cons:
- None!
Summary
Problem: WordPress canonical redirect interferes with React Router
Solution: Disable canonical redirects for SPA routes using redirect_canonical filter
Result: Direct product URLs now work correctly! ✅
Files Modified:
includes/Frontend/TemplateOverride.php- Added redirect handler
Test: Navigate to /product/edukasi-anak directly - should work!