Configure Dynamic Bundles
Learn how to implement dynamic bundle configuration in your storefront. For understanding the configuration structure and concepts, see Understanding Bundle Configuration.
Prerequisites
Before implementing bundle configuration, ensure you understand:
- Bundle configuration structure
- Validation requirements
- How to fetch bundle and component data (see Get Bundle)
Configure Bundle with SDK
Use configureByContextProduct
to generate a valid bundle configuration:
import { configureByContextProduct } from '@epcc-sdk/sdks-shopper';
async function configureDynamicBundle(
bundleId: string,
selectedOptions: BundleConfiguration["selected_options"]
) {
try {
const response = await configureByContextProduct({
path: { product_id: bundleId },
body: {
data: {
selected_options: selectedOptions
}
}
});
// Returns configured bundle with updated price
return {
success: true,
configuredBundle: response.data,
configuration: response.data?.meta?.bundle_configuration
};
} catch (error) {
return {
success: false,
error: error.message || 'Failed to configure bundle'
};
}
}
Example: Bundle Configurator
Simplified implementation with validation and price updates:
function BundleConfigurator({ bundle, componentProducts }) {
const [selectedOptions, setSelectedOptions] = useState({});
const [configuredBundle, setConfiguredBundle] = useState(null);
const [isConfiguring, setIsConfiguring] = useState(false);
const [validationErrors, setValidationErrors] = useState([]);
const components = bundle.attributes?.components || {};
// Validate and configure on selection change
useEffect(() => {
const validation = validateBundleSelection(components, selectedOptions);
setValidationErrors(validation.errors);
if (validation.isValid && Object.keys(selectedOptions).length > 0) {
configureBundle();
}
}, [selectedOptions]);
const configureBundle = async () => {
setIsConfiguring(true);
const result = await configureDynamicBundle(bundle.id, selectedOptions);
if (result.success) {
setConfiguredBundle(result.configuredBundle);
}
setIsConfiguring(false);
};
const handleAddToCart = async () => {
const configuration = configuredBundle?.data?.meta?.bundle_configuration;
if (!configuration) return;
const cartId = getCartId();
await manageCarts({
path: { cartID: cartId },
body: {
data: {
type: 'cart_item',
id: bundle.id,
quantity: 1,
bundle_configuration: configuration
}
}
});
};
const currentPrice = configuredBundle?.data?.meta?.display_price?.without_tax?.formatted
|| bundle.meta?.display_price?.without_tax?.formatted;
return (
<>
<h3>Price: {isConfiguring ? 'Updating...' : currentPrice}</h3>
{validationErrors.map((error, idx) => (
<p key={idx}>{error}</p>
))}
{/* Render component selection UI here */}
<button
onClick={handleAddToCart}
disabled={validationErrors.length > 0 || !configuredBundle}
>
Add to Cart
</button>
</>
);
}
Configuration Persistence
To improve user experience, you can persist bundle configurations across sessions. See Configuration Persistence for implementation details including:
- Saving configurations to URL for sharing
- Using localStorage for returning users
- Handling stale configuration data
Example usage in your component:
// On mount, restore saved configuration
useEffect(() => {
const savedConfig = restoreConfigurationFromUrl();
if (savedConfig) {
setSelectedOptions(savedConfig);
}
}, []);
// Save configuration when it changes
useEffect(() => {
if (Object.keys(selectedOptions).length > 0) {
saveConfigurationToUrl(bundle.id, selectedOptions);
}
}, [selectedOptions]);
Error Handling
Common error scenarios to handle:
- 422 Validation Error: Invalid bundle configuration
- 404 Not Found: Bundle or component product not found
- Stock Issues: Component out of stock
- Generic Errors: Network or server issues
Implementation Tips
When building bundle configurators:
- Validate before configuring: Check selections meet requirements before API calls
- Debounce API calls: Wait for user to finish selecting (300-500ms)
- Show loading states: Indicate when prices are updating
- Handle errors gracefully: Provide clear feedback for validation errors
- Cache component data: Component products rarely change
For understanding the configuration data structure and concepts, see Understanding Bundle Configuration.
Next Steps
With your bundle configurator implemented:
- Bundle Pricing Strategies - Display dynamic pricing
- Add Bundle to Cart - Complete the purchase flow
- Bundle Selection Patterns - Advanced UI patterns