Skip to main content

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:

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:

References​

Ask External AI