Push Configuration
Push Configuration
What is push configuration?
Push configuration defines how your website handles web push notifications, including Service Worker setup, VAPID keys, permission handling, and notification display. It follows this flow:
VAPID key → Service Worker registration → Permission request → Notification delivery
Benefits:
- Real-time notifications — Send notifications even when users aren’t on your site
- User engagement — Re-engage users with timely, relevant content
- Cross-platform — Works on desktop and mobile browsers
- Customizable — Control when and how notifications are shown
- Analytics integration — Track notification performance and user behavior
Push notification types
- Permission Requests: Ask users to allow notifications for initial setup and re-engagement to build notification audience.
- Direct Notifications: Send immediate notifications for breaking news and alerts to enable real-time communication.
- Scheduled Notifications: Send notifications at specific times for reminders and promotions to enable timed engagement.
- Triggered Notifications: Send based on user actions like abandoned cart and welcome messages for contextual messaging.
Push configuration structure
key(string, required): VAPID public key - Server authentication for secure push delivery.push_serviceworker(string, default:/sw.js): Service Worker path - Background script for notification handling.serviceWorkerScope(string, auto-detected): Service Worker scope - Control which pages can receive notifications.push_enable_subdomain_subscription(boolean, default:false): Subdomain subscription - Separate notification preferences per subdomain.prompts(array, default:[]): Modal prompts - Pre-permission dialogs to improve conversion and comply with browser requirements.
Basic push configuration
{
"key": "BExxx...VAPID...",
"push_serviceworker": "/sw.js",
"serviceWorkerScope": "/",
"push_enable_subdomain_subscription": false
}
Push configuration options
VAPID Key (key)
Purpose: VAPID (Voluntary Application Server Identification) public key enables secure push notification delivery by authenticating your server to browser push services.
Why it’s required:
- Security: Prevents unauthorized servers from sending notifications to your users
- Browser compliance: Chrome, Firefox, and Safari require VAPID for push notifications
- User trust: Users know notifications come from verified, legitimate sources
- Spam prevention: Blocks malicious actors from sending fake notifications
Requirements:
- Length: Must be at least 85 characters
- Format: Base64-encoded string
- Security: Must match your server’s VAPID private key
- HTTPS: Only works over HTTPS connections
Examples:
{ "key": "BExxx...VAPID...PUBLIC...KEY..." }
{ "key": "BEl62iUYgUivxIkv69yViEuiBIa40HI8..." }
Generation: VAPID keys are generated using your server-side application. The public key is used in the SDK configuration.
Validation: SDK validates key length and availability before registering Service Worker.
Service Worker Path (push_serviceworker)
Purpose: Defines the location of your Service Worker file that handles push notifications in the background, even when your website is closed.
Why it’s important:
- Background processing: Service Worker runs independently of your website
- Notification delivery: Receives and displays notifications when site is closed
- Offline capability: Can cache and queue notifications for later delivery
- Performance: Lightweight background script doesn’t impact site performance
Supported paths:
- Root path:
/sw.js- Controls entire website - Subdirectory:
/js/sw.js- Controls specific sections - Custom path:
/custom-service-worker.js- Branded naming - CDN path:
https://cdn.example.com/sw.js- External hosting
Examples:
{ "push_serviceworker": "/sw.js" }
{ "push_serviceworker": "/js/service-worker.js" }
{ "push_serviceworker": "/custom-sw.js" }
Fallback options: SDK also checks for customsw, pushserviceworker, and service_worker_path if push_serviceworker is not provided.
Requirements: Service Worker file must exist and be accessible via HTTPS.
Service Worker Scope (serviceWorkerScope)
Purpose: Controls which parts of your website the Service Worker can manage, providing security and performance benefits.
Why scope matters:
- Security: Prevents Service Worker from accessing unauthorized parts of your site
- Performance: Smaller scope means faster registration and less memory usage
- Multi-app architecture: Different Service Workers for different app sections
- Isolation: Prevents conflicts between different parts of your application
Auto-detection: If not specified, SDK automatically detects scope from Service Worker path:
/sw.js→ scope:/(entire site)/js/sw.js→ scope:/js/(only JS directory)/custom/sw.js→ scope:/custom/(only custom directory)
Examples:
{ "serviceWorkerScope": "/" } // Entire website
{ "serviceWorkerScope": "/app/" } // Only /app/ section
{ "serviceWorkerScope": "/dashboard/" } // Only dashboard area
Use cases:
- Root scope (
/): Service Worker controls entire site - best for simple websites - Limited scope (
/app/): Service Worker only controls specific sections - better for complex apps - Multi-app: Different Service Workers for different app sections - enterprise applications
Subdomain Subscription (push_enable_subdomain_subscription)
Purpose: Creates separate push notification subscriptions for each subdomain, enabling targeted messaging and better user experience.
Why use subdomain subscriptions:
- Brand separation: Different notifications for different brands (brand1.example.com vs brand2.example.com)
- User preferences: Users can opt-in to notifications from specific subdomains only
- A/B testing: Test different notification strategies per subdomain
- Compliance: Meet regional requirements for different markets
- Analytics: Track notification performance per subdomain separately
Behavior:
false(default): Single subscription for entire domain - simpler setuptrue: Separate subscriptions per subdomain - more granular control
Storage keys:
- Single domain:
push- one subscription for all subdomains - Subdomain enabled:
psh<hash>where hash is checksum of hostname - unique per subdomain
Examples:
{ "push_enable_subdomain_subscription": false } // Single subscription for all
{ "push_enable_subdomain_subscription": true } // Separate per subdomain
Use cases:
- Multi-tenant apps: Different notifications for different tenants
- A/B testing: Different notification strategies per subdomain
- Brand separation: Separate notification preferences per brand
- Regional compliance: Different notification rules per region
Modal Prompts (prompts)
Purpose: Custom modal dialogs shown before the native browser permission request to improve conversion rates and comply with browser requirements.
Why modal prompts are essential:
- Browser compliance: Chrome requires user gesture interaction before showing native permission prompt (prevents violations)
- Higher conversion: 3-5x better permission acceptance rates compared to direct native prompts
- User education: Explain the value of notifications before asking for permission
- Better UX: Custom branding, messaging, and design that matches your site
- Targeted messaging: Show different prompts to different user segments
- A/B testing: Test different approaches to find what works best
Browser requirements:
- Chrome: Requires user gesture (click, scroll, etc.) before native prompt
- Firefox: More lenient but still benefits from user education
- Safari: Strict about permission timing and user context
Structure: Array of modal configuration objects with triggers and filters.
Examples:
{
"prompts": [
{
"id": "push-permission-modal",
"template": "push-permission-template",
"triggers": [{ "type": "pageView" }],
"filters": [
{ "c": "{{data.user_segment}}", "o": "eq", "m": "engaged" }
],
"options": {
"theme": "light",
"animation": "slide-up"
}
}
]
}
Benefits:
- Higher conversion: Explain value before requesting permission
- Better UX: Custom messaging and branding
- Targeted prompts: Show only to relevant users
- A/B testing: Test different prompt strategies
- Compliance: Meet browser requirements for user gesture
Integration: Uses same modal system as regular modals with group: 'push' for identification.
Push configuration examples
For comprehensive push configuration examples including basic setup, advanced features, modal prompts, e-commerce integration, and multi-brand setups, see Push configuration examples.
Push notification flow
Registration process
- VAPID validation - Check key length and format
- Service Worker registration - Register SW with specified path and scope
- Permission check - Check current notification permission status
- Subscription management - Handle existing subscriptions and repairs
- Event binding - Set up push event listeners
Permission states
granted: User allowed notifications - Subscribe to push notifications.denied: User blocked notifications - Show alternative engagement options.prompt: Permission not requested yet - Show custom prompt or native prompt.closed: User dismissed prompt - Retry with different strategy.auto-block: Browser auto-blocked - Use alternative engagement methods.
Error handling
// SDK automatically tracks push errors
Hood('on', 'pushError', (error) => {
console.log('Push error:', error);
// Handle specific error types
});
Common error scenarios:
- Invalid VAPID key
- Service Worker registration failure
- Permission denied
- Network connectivity issues
- Browser compatibility problems
Integration with other features
Push + Modals
Push prompts can be integrated with the modal system:
{
"push_config": {
"key": "BExxx...VAPID...",
"push_serviceworker": "/sw.js",
"prompts": [
{
"id": "push-permission-modal",
"template": "push-permission-template",
"triggers": [{ "type": "pageView" }],
"filters": [
{ "c": "{{data.push_eligible}}", "o": "eq", "m": "true" }
],
"options": {
"theme": "light",
"animation": "slide-up",
"limit_type": "session",
"limit_count": 1
}
}
]
}
}
Push + Analytics
Track push notification performance:
// Track permission requests
Hood('trackEvent', 'push_permission_requested', {
prompt_type: 'modal',
user_segment: 'premium'
});
// Track permission granted
Hood('trackEvent', 'push_permission_granted', {
method: 'native_prompt',
time_to_grant: 5000
});
Push + User Properties
Use user data for targeted push prompts:
{
"push_config": {
"key": "BExxx...VAPID...",
"push_serviceworker": "/sw.js",
"prompts": [
{
"id": "personalized-push-modal",
"template": "personalized-push-template",
"triggers": [{ "type": "pageView" }],
"filters": [
{ "c": "{{data.subscription_tier}}", "o": "eq", "m": "premium" },
{ "c": "{{data.push_opted_out}}", "o": "neq", "m": "true" }
]
}
]
}
}
Best practices
Performance optimization
Performance Tips
- Early registration: Register Service Worker as early as possible
- Efficient SW: Keep Service Worker file lightweight
- Proper scope: Use appropriate Service Worker scope
- Error handling: Implement robust error handling for registration failures
- Fallback strategies: Have alternative engagement methods for blocked users
User experience
- Clear value proposition: Explain benefits before requesting permission
- Timing: Request permission at optimal moments (after engagement)
- Frequency: Don’t spam users with permission requests
- Custom prompts: Use modal prompts to improve conversion rates
- Respect user choice: Honor permission decisions
Security considerations
- HTTPS only: Push notifications only work over HTTPS
- VAPID security: Keep VAPID private key secure on server
- Scope limitations: Use appropriate Service Worker scope
- Content validation: Validate notification content before sending
Troubleshooting
If push notifications aren’t working as expected, try these solutions:
Service Worker not registering?
- Verify the Service Worker file exists at the specified path
- Check that the file is accessible over HTTPS (not HTTP)
- Inspect browser console for registration errors
- Test the path directly in your browser (e.g.,
https://yoursite.com/sw.js) - Ensure the Service Worker scope is correct for your domain structure
VAPID key invalid?
- Verify the key is at least 85 characters long
- Check that it’s properly base64-encoded
- Ensure you’re using the public key (not the private key)
- Confirm the key matches your server’s VAPID configuration
- Test with a fresh key pair if issues persist
Permission denied by user?
- Respect the user’s choice - don’t repeatedly ask
- Provide alternative engagement methods (email, SMS, in-app messages)
- Explain the value of notifications before requesting permission
- Consider using modal prompts to improve conversion rates
- Track denial reasons to improve your permission strategy
Notifications not showing?
- Check that the Service Worker is active:
navigator.serviceWorker.getRegistrations() - Verify notification permission is granted:
Notification.permission === 'granted' - Test with a simple notification to isolate the issue
- Check browser console for push event errors
- Ensure the Service Worker is properly handling push events
Cross-domain or scope issues?
- Verify the Service Worker scope matches your domain structure
- Check that the Service Worker path is correct for your setup
- Ensure HTTPS is properly configured (including certificates)
- Test with root scope (
/) first, then narrow down if needed - Review browser DevTools → Application → Service Workers for status
Debug mode
Enable debug logging for push notifications:
// Enable debug mode
Hood('config', 'debug', true);
// Check push status
Hood('pushStatus', (status) => {
console.log('Push status:', status);
});
Testing
Test push configuration in development:
// Test Service Worker registration
navigator.serviceWorker.getRegistrations().then(registrations => {
console.log('SW registrations:', registrations);
});
// Test permission status
navigator.permissions.query({name: 'notifications'}).then(result => {
console.log('Permission status:', result.state);
});