Added SHIPPING_ADDON_RESEARCH.md with findings on: ## Key Insights: 1. **Standard vs Indonesian Plugins** - Standard: Simple settings, no custom fields - Indonesian: Complex API, custom checkout fields, subdistrict 2. **How Indonesian Plugins Work** - Add custom checkout fields (subdistrict) - Require origin configuration in wp-admin - Make real-time API calls during checkout - Calculate rates based on origin-destination pairing 3. **Why They're Complex** - 7,000+ subdistricts in Indonesia - Each courier has different rates per subdistrict - Can't pre-calculate (must use API) - Origin + destination required ## WooNooW Strategy: ✅ DO: - Display all methods from WooCommerce API - Show enable/disable toggle - Show basic settings (title, cost, min_amount) - Link to WooCommerce for complex config ❌ DON'T: - Try to manage custom checkout fields - Try to calculate rates - Try to show all plugin settings - Interfere with plugin functionality ## Next Steps: 1. Detect complex shipping plugins 2. Show different UI for complex methods 3. Add "Configure in WooCommerce" button 4. Hide settings form for complex methods Result: Simplified UI for standard methods, full power for complex plugins!
9.8 KiB
Shipping Addon Integration Research
Problem Statement
Indonesian shipping plugins (Biteship, Woongkir, etc.) have complex requirements:
- Origin address - configured in wp-admin
- Subdistrict field - custom checkout field
- Real-time API calls - during cart/checkout
- Custom field injection - modify checkout form
Question: How can WooNooW SPA accommodate these plugins without breaking their functionality?
How WooCommerce Shipping Addons Work
Standard WooCommerce Pattern
class My_Shipping_Method extends WC_Shipping_Method {
public function calculate_shipping($package = array()) {
// 1. Get settings from $this->get_option()
// 2. Calculate rates based on package
// 3. Call $this->add_rate($rate)
}
}
Key Points:
- ✅ Extends
WC_Shipping_Method - ✅ Uses WooCommerce hooks:
woocommerce_shipping_init,woocommerce_shipping_methods - ✅ Settings stored in
wp_optionstable - ✅ Rates calculated during
calculate_shipping()
Indonesian Shipping Plugins (Biteship, Woongkir, etc.)
How They Differ from Standard Plugins
1. Custom Checkout Fields
// They add custom fields to checkout
add_filter('woocommerce_checkout_fields', function($fields) {
$fields['billing']['billing_subdistrict'] = array(
'type' => 'select',
'label' => 'Subdistrict',
'required' => true,
'options' => get_subdistricts() // API call
);
return $fields;
});
2. Origin Configuration
- Stored in plugin settings (wp-admin)
- Used for API calls to calculate distance/cost
- Not exposed in standard WooCommerce shipping settings
3. Real-time API Calls
public function calculate_shipping($package) {
// Get origin from plugin settings
$origin = get_option('biteship_origin_subdistrict_id');
// Get destination from checkout field
$destination = $package['destination']['subdistrict_id'];
// Call external API
$rates = biteship_api_get_rates($origin, $destination, $weight);
foreach ($rates as $rate) {
$this->add_rate($rate);
}
}
4. AJAX Updates
// Update shipping when subdistrict changes
jQuery('#billing_subdistrict').on('change', function() {
jQuery('body').trigger('update_checkout');
});
Why Indonesian Plugins Are Complex
1. Geographic Complexity
- Indonesia has 34 provinces, 514 cities, 7,000+ subdistricts
- Shipping cost varies by subdistrict (not just city)
- Standard WooCommerce only has: Country → State → City → Postcode
2. Multiple Couriers
- Each courier has different rates per subdistrict
- Real-time API calls required (can't pre-calculate)
- Some couriers don't serve all subdistricts
3. Origin-Destination Pairing
- Cost depends on origin subdistrict + destination subdistrict
- Origin must be configured in admin
- Destination selected at checkout
How WooNooW SPA Should Handle This
✅ What WooNooW SHOULD Do
1. Display Methods Correctly
// Our current approach is CORRECT
const { data: zones } = useQuery({
queryKey: ['shipping-zones'],
queryFn: () => api.get('/settings/shipping/zones')
});
- ✅ Fetch zones from WooCommerce API
- ✅ Display all methods (including Biteship, Woongkir)
- ✅ Show enable/disable toggle
- ✅ Link to WooCommerce settings for advanced config
2. Expose Basic Settings Only
// Show only common settings
- Display Name (title)
- Cost (if applicable)
- Min Amount (if applicable)
- ✅ Don't try to show ALL settings
- ✅ Complex settings → "Edit in WooCommerce" button
3. Respect Plugin Behavior
- ✅ Don't interfere with checkout field injection
- ✅ Don't modify
calculate_shipping()logic - ✅ Let plugins handle their own API calls
❌ What WooNooW SHOULD NOT Do
1. Don't Try to Manage Custom Fields
// ❌ DON'T DO THIS
const subdistrictField = {
type: 'select',
options: await fetchSubdistricts()
};
- ❌ Subdistrict fields are managed by shipping plugins
- ❌ They inject fields via WooCommerce hooks
- ❌ WooNooW SPA doesn't control checkout page
2. Don't Try to Calculate Rates
// ❌ DON'T DO THIS
const rate = await biteshipAPI.getRates(origin, destination);
- ❌ Rate calculation is plugin-specific
- ❌ Requires API keys, origin config, etc.
- ❌ Should happen during checkout, not in admin
3. Don't Try to Show All Settings
// ❌ DON'T DO THIS
<Input label="Origin Subdistrict ID" />
<Input label="API Key" />
<Input label="Courier Selection" />
- ❌ Too complex for simplified UI
- ❌ Each plugin has different settings
- ❌ Better to link to WooCommerce settings
Comparison: Global vs Indonesian Shipping
Global Shipping Plugins (ShipStation, EasyPost, etc.)
Characteristics:
- ✅ Standard address fields (Country, State, City, Postcode)
- ✅ Pre-calculated rates or simple API calls
- ✅ No custom checkout fields needed
- ✅ Settings fit in standard WooCommerce UI
Example: Flat Rate
public function calculate_shipping($package) {
$rate = array(
'label' => $this->title,
'cost' => $this->get_option('cost')
);
$this->add_rate($rate);
}
Indonesian Shipping Plugins (Biteship, Woongkir, etc.)
Characteristics:
- ⚠️ Custom address fields (Province, City, District, Subdistrict)
- ⚠️ Real-time API calls with origin-destination pairing
- ⚠️ Custom checkout field injection
- ⚠️ Complex settings (API keys, origin config, courier selection)
Example: Biteship
public function calculate_shipping($package) {
$origin_id = get_option('biteship_origin_subdistrict_id');
$dest_id = $package['destination']['subdistrict_id'];
$response = wp_remote_post('https://api.biteship.com/v1/rates', array(
'headers' => array('Authorization' => 'Bearer ' . $api_key),
'body' => json_encode(array(
'origin_area_id' => $origin_id,
'destination_area_id' => $dest_id,
'couriers' => $this->get_option('couriers'),
'items' => $package['contents']
))
));
$rates = json_decode($response['body'])->pricing;
foreach ($rates as $rate) {
$this->add_rate(array(
'label' => $rate->courier_name . ' - ' . $rate->courier_service_name,
'cost' => $rate->price
));
}
}
Recommendations for WooNooW SPA
✅ Current Approach is CORRECT
Our simplified UI is perfect for:
- Standard shipping methods (Flat Rate, Free Shipping, Local Pickup)
- Simple third-party plugins (basic rate calculators)
- Non-tech users who just want to enable/disable methods
✅ For Complex Plugins (Biteship, Woongkir)
Strategy: "View-Only + Link to WooCommerce"
// In the accordion, show:
<AccordionItem>
<AccordionTrigger>
🚚 Biteship - JNE REG [On]
Rp 15,000 (calculated at checkout)
</AccordionTrigger>
<AccordionContent>
<Alert>
This is a complex shipping method with advanced settings.
<Button asChild>
<a href={wcAdminUrl + '/admin.php?page=biteship-settings'}>
Configure in WooCommerce
</a>
</Button>
</Alert>
{/* Only show basic toggle */}
<ToggleField
label="Enable/Disable"
value={method.enabled}
onChange={handleToggle}
/>
</AccordionContent>
</AccordionItem>
✅ Detection Logic
// Detect if method is complex
const isComplexMethod = (method: ShippingMethod) => {
const complexPlugins = [
'biteship',
'woongkir',
'anteraja',
'shipper',
// Add more as needed
];
return complexPlugins.some(plugin =>
method.id.includes(plugin)
);
};
// Render accordingly
{isComplexMethod(method) ? (
<ComplexMethodView method={method} />
) : (
<SimpleMethodView method={method} />
)}
Testing Strategy
✅ What to Test in WooNooW SPA
-
Method Display
- ✅ Biteship methods appear in zone list
- ✅ Enable/disable toggle works
- ✅ Method name displays correctly
-
Settings Link
- ✅ "Edit in WooCommerce" button works
- ✅ Opens correct settings page
-
Don't Break Checkout
- ✅ Subdistrict field still appears
- ✅ Rates calculate correctly
- ✅ AJAX updates work
❌ What NOT to Test in WooNooW SPA
- ❌ Rate calculation accuracy
- ❌ API integration
- ❌ Subdistrict field functionality
- ❌ Origin configuration
These are the shipping plugin's responsibility!
Conclusion
WooNooW SPA's Role:
✅ Simplified management for standard shipping methods
✅ View-only + link for complex plugins
✅ Don't interfere with plugin functionality
Shipping Plugin's Role:
✅ Handle complex settings (origin, API keys, etc.)
✅ Inject custom checkout fields
✅ Calculate rates via API
✅ Manage courier selection
Result:
✅ Non-tech users can enable/disable methods easily
✅ Complex configuration stays in WooCommerce admin
✅ No functionality is lost
✅ Best of both worlds! 🎯
Implementation Plan
Phase 1: Detection (Current)
- Display all methods from WooCommerce API
- Show enable/disable toggle
- Show basic settings (title, cost, min_amount)
Phase 2: Complex Method Handling (Next)
- Detect complex shipping plugins
- Show different UI for complex methods
- Add "Configure in WooCommerce" button
- Hide settings form for complex methods
Phase 3: Documentation (Final)
- Add help text explaining complex methods
- Link to plugin documentation
- Add troubleshooting guide
Last Updated: Nov 9, 2025
Status: Research Complete ✅