Storefront Hooks Documentation
20 min
Storefront hooks provide a communication interface between the Purple Experience and custom JavaScript code (custom.js). This system allows external code to extend and customize Experience's behavior without modifying the core application.
Setup
Hooks are defined in the custom.js file and registered on the global window.storefrontHooks object. The hooks are triggered at specific points during the application lifecycle.
// Example setup in custom.js
window.storefrontHooks = {
onPurpleServiceInit: () => {
console.log('Purple service initialized');
},
// ... other hooks
};Available Hooks
Service Lifecycle Hooks
onPurpleServiceInit()
- Triggered: When the PurpleService is fully initialized and ready to serve requests
- Use case: Set up initial configurations
- Parameters: None
- Return: void
window.storefrontHooks.onPurpleServiceInit = () => {
// Initialize tracking services, ads, or other external integrations
};Navigation Hooks
onNavigationEnd(params)
- Triggered: After Angular's NavigationEnd event. Despite its name, it is actually triggered at the beginning of the navigation process, right when the page starts rendering.
- Use case: Track page views, update analytics
- Parameters:
- event: Angular NavigationEnd event object
- router: Angular Router instance
- viewContext: Context data object
- Return: void
window.storefrontHooks.onNavigationEnd = (params) => {
console.log('Navigated to:', params.event.url);
// Track page views
};onNavigationStable(params)
- Triggered: When the app becomes stable after Angular navigation (including initial load)
- Use case: Refresh ads after route changes, perform post-navigation actions
- Parameters:
- All parameters from onNavigationEnd
- previousUrl: Previous URL (optional)
- currentUrl: Current URL
- Return: void
window.storefrontHooks.onNavigationStable = (params) => {
// Ideal for refreshing ads after route changes
};Content Hooks
onContentLoaded(params)
- Triggered: After a content body component successfully loads the content along with its resources
- Use case: Content-specific tracking
- Parameters:
- content: CatalogContent object
- post: CatalogPost object (for bundle content)
- context: Context data object
- Return: void
window.storefrontHooks.onContentLoaded = (params) => {
console.log('Content loaded:', params.content.name);
// Track content views
};Purchase Hooks
beforeContentPurchase(purchaseInfo)
- Triggered: Before a content purchase is performed, when processPurchaseAction is performed
- Use case: Validate purchases, show custom purchase flows, intercept purchases
- Parameters:
- purchaseInfo.actionConfig: Purchase action configuration
- Return: HookBeforePurchaseResult (continue | cancel | error)
window.storefrontHooks.beforeContentPurchase = async (purchaseInfo) => {
// Custom validation or purchase flow
if (customValidation()) {
return { type: 'continue' };
} else {
return { type: 'cancel' };
}
};beforeSubscriptionPurchase(purchaseInfo)
- Triggered: Before a subscription purchase is performed, when processSubscribeAction is performed
- Use case: Custom subscription flows, validation
- Parameters:
- purchaseInfo.actionConfig: Subscription action configuration
- Return: HookBeforePurchaseResult (continue | cancel | error)
window.storefrontHooks.beforeSubscriptionPurchase = async (purchaseInfo) => {
// Custom subscription logic
return { type: 'continue' };
};User State Hooks
entitlementChanged(params)
- Triggered: When user entitlement changes (login/logout/subscription changes)
- Use case: Update user-specific UI, sync external services
- Parameters:
- newState: Current EntitlementUserData
- oldState: Previous EntitlementUserData (optional)
- Return: void
window.storefrontHooks.entitlementChanged = (params) => {
console.log('User entitlement changed:', params.newState);
// Update external user profiles, analytics
};subscriptionsChanged(params)
- Triggered: When user subscriptions change, when processSubscribeAction is performed
- Use case: Track subscription changes, update UI
- Parameters:
- subscriptions: Array of AppSubscription objects
- Return: void
window.storefrontHooks.subscriptionsChanged = (params) => {
console.log('Subscriptions updated:', params.subscriptions.length);
// Update subscription-dependent features
};Advertisement Hooks
onAdInit()
- Triggered: To initialize pre-bid scripts for ads (only for GPT)
- Use case: Set up ad networks, initialize bidding
- Parameters: None
- Return: void
window.storefrontHooks.onAdInit = () => {
// Initialize ad networks, prebid scripts
};beforeRenderAd(params)
- Triggered: Before an ad is rendered (only for GPT)
- Use case: Custom ad rendering logic, ad blocking
- Parameters:
- id: Ad slot identifier
- slot: Ad slot object
- config: Ad configuration
- refresh: Whether this is a refresh (optional)
- Return: boolean (true = continue with default rendering, false = skip)
window.storefrontHooks.beforeRenderAd = (params) => {
console.log('Rendering ad:', params.id);
// Return false to prevent default ad rendering
return true;
};isAdRefreshPaused()
- Triggered: To check if ad refresh should be paused (only for GPT)
- Use case: Pause ads during video playback, user interactions
- Parameters: None
- Return: boolean (true = pause refresh, false = allow refresh)
window.storefrontHooks.isAdRefreshPaused = () => {
// Check if ads should be paused
return isVideoPlaying();
};isAdDisabled(id)
- Triggered: To check if specific ads should be disabled
- Use case: Disable ads on certain devices or screen sizes
- Parameters:
- id: Ad identifier
- Return: boolean (true = disable ad, false = show ad)
window.storefrontHooks.isAdDisabled = (id) => {
// Disable ads on mobile devices
return window.innerWidth < 768;
};UI Hooks
getIntersectionMargin()
- Triggered: To get intersection margin for lazy loading
- Use case: Control when components load based on viewport proximity
- Parameters: None
- Return: string (CSS margin value, e.g., "500px")
window.storefrontHooks.getIntersectionMargin = () => {
// Load components 500px before they become visible
return "500px";
};Purchase Result Types
When implementing purchase hooks, return one of these result types:
- { type: 'continue' } - Proceed with the platform's purchase
- { type: 'cancel' } - Silently cancel the purchase process
- { type: 'error', code?: ERROR_CODE } - Cancel with error (code unused for subscriptions)
Example Implementation
// Complete example in custom.js
window.storefrontHooks = {
onPurpleServiceInit: () => {
console.log('Storefront initialized');
// Initialize analytics, ads, etc.
},
onNavigationStable: (params) => {
// Track page views
gtag('config', 'GA_MEASUREMENT_ID', {
page_path: params.currentUrl
});
},
beforeContentPurchase: async (purchaseInfo) => {
// Show custom purchase dialog
const proceed = await showCustomPurchaseDialog(purchaseInfo);
return proceed ? { type: 'continue' } : { type: 'cancel' };
},
entitlementChanged: (params) => {
// Update user session in external systems
}
};