Skip to main content
Technology & EngineeringNotification Services279 lines

Roost

Integrate Roost for real-time web push notifications directly from your web application.

Quick Summary16 lines
You are a web developer focused on user engagement and retention, leveraging Roost to deliver targeted web push notifications. Roost provides a streamlined solution for capturing subscribers, managing permissions, and sending real-time messages to users directly in their browser, enhancing re-engagement for web-based applications and services.

## Key Points

*   **Personalize Messages**: Use available user data (e.g., username, preferred language, recent activity) to make notifications highly relevant and engaging.
*   **Deep Linking**: Always include a `url` in your notification payload that directs users to the most relevant page within your application, improving user experience and conversion.
*   **Segment Your Audience**: Utilize Roost's tagging or user ID features to send targeted notifications to specific groups of users, avoiding spam and increasing relevance.
*   **Optimize Notification Content**: Keep titles concise and bodies informative. Use emojis sparingly for emphasis, and consider rich notification features like images for greater impact.
*   **Monitor Analytics**: Regularly check Roost's analytics dashboard for delivery rates, click-through rates, and unsubscribe rates. Use this data to refine your notification strategy.
*   **Graceful Degradation**: Ensure your application functions well even for users who deny notification permissions or use browsers that don't support web push.
*   **Prompting on Page Load.** Asking for notification permission immediately upon a user's first visit is intrusive and often leads to denials; wait for user engagement before asking.
*   **Spamming Users.** Sending too many notifications, or notifications that lack value, quickly leads to user fatigue and unsubscribes; prioritize quality over quantity.
*   **Generic Messages.** Sending the same, untargeted message to all users reduces engagement and perceived relevance; personalize messages based on user data and behavior.
*   **Hardcoding API Keys Client-Side.** Never embed your Roost API Secret (or any sensitive API key) directly into client-side code; always use a secure backend service to trigger notifications.
skilldb get notification-services-skills/RoostFull skill: 279 lines
Paste into your CLAUDE.md or agent config

You are a web developer focused on user engagement and retention, leveraging Roost to deliver targeted web push notifications. Roost provides a streamlined solution for capturing subscribers, managing permissions, and sending real-time messages to users directly in their browser, enhancing re-engagement for web-based applications and services.

Core Philosophy

Roost's core philosophy centers on simplifying web push notification integration and maximizing user re-engagement. It abstracts away the complexities of Service Workers, VAPID key management, and browser-specific implementations, providing a unified JavaScript SDK for the client-side and a robust API for server-side message triggering. You choose Roost when you need to quickly implement a reliable web push solution without deep dives into browser push protocols, focusing instead on content and timing.

The service emphasizes a direct-to-browser communication channel, enabling you to reach users even when they are not actively on your website. This makes it ideal for transactional alerts, promotional offers, content updates, or any scenario where timely, non-intrusive communication can drive users back to your application. Roost handles the infrastructure, ensuring high deliverability and providing analytics on subscription and engagement rates.

Setup

Integrating Roost typically involves including their client-side JavaScript SDK and configuring your server-side application to interact with their API using your API key.

Client-Side SDK Integration

Add the Roost SDK script to your web page, ideally just before the closing </body> tag. This script handles the installation of the necessary Service Worker and initializes the Roost client.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>My Roost-Enabled App</title>
</head>
<body>
    <h1>Welcome to My App</h1>
    <p>Click the button to enable notifications!</p>
    <button id="enableNotifications">Enable Notifications</button>

    <script src="https://cdn.roost.com/roost.js" data-app-key="YOUR_ROOST_APP_KEY"></script>
    <script>
        // Initialize Roost after the SDK is loaded
        Roost.init({
            appKey: 'YOUR_ROOST_APP_KEY',
            // Optional: specify a custom service worker path
            serviceWorkerPath: '/roost-sw.js'
        });

        document.getElementById('enableNotifications').addEventListener('click', () => {
            Roost.askPermission();
        });
    </script>
</body>
</html>

Server-Side API Configuration (Node.js Example)

For sending notifications, you'll interact with the Roost REST API from your backend. Store your API Secret securely.

// Install the Roost Node.js SDK (hypothetical, as Roost might use direct HTTP calls)
// npm install @roost/sdk --save
const Roost = require('@roost/sdk'); // Assuming a Roost SDK exists for illustration

const ROOST_APP_KEY = process.env.ROOST_APP_KEY; // Your public app key
const ROOST_API_SECRET = process.env.ROOST_API_SECRET; // Your private API secret

if (!ROOST_APP_KEY || !ROOST_API_SECRET) {
    console.error("Roost API keys not set. Please set ROOST_APP_KEY and ROOST_API_SECRET environment variables.");
    process.exit(1);
}

const roostClient = new Roost.Client({
    appKey: ROOST_APP_KEY,
    apiSecret: ROOST_API_SECRET
});

// Example usage:
async function sendWelcomeNotification(userId) {
    try {
        const response = await roostClient.sendNotification({
            title: 'Welcome!',
            body: 'Thanks for subscribing to our notifications!',
            url: 'https://your-app.com/welcome',
            target: {
                userId: userId // Target a specific user
            }
        });
        console.log('Welcome notification sent:', response);
    } catch (error) {
        console.error('Failed to send welcome notification:', error);
    }
}

// Call this function when a new user subscribes or registers
// sendWelcomeNotification('user_12345');

Key Techniques

1. Requesting Notification Permissions Strategically

Do not ask for permission immediately on page load. Instead, provide context and a clear call to action. Roost simplifies the underlying browser API calls.

// Client-side script
// Assuming Roost.init() has already been called
document.addEventListener('DOMContentLoaded', () => {
    const subscribeButton = document.getElementById('subscribe-button');
    const notificationStatus = document.getElementById('notification-status');

    // Check current permission status
    if (Roost.isPushEnabled()) {
        notificationStatus.textContent = 'Notifications are enabled!';
        subscribeButton.style.display = 'none';
    } else {
        notificationStatus.textContent = 'Notifications are currently disabled.';
        subscribeButton.style.display = 'block';
    }

    subscribeButton.addEventListener('click', async () => {
        try {
            await Roost.askPermission(); // Prompts the user
            if (Roost.isPushEnabled()) {
                notificationStatus.textContent = 'Notifications are now enabled!';
                subscribeButton.style.display = 'none';
                // Optionally, send the subscription ID to your backend if needed
                // const subscriptionId = Roost.getSubscriptionId();
                // sendSubscriptionToServer(subscriptionId);
            } else {
                notificationStatus.textContent = 'Notifications remain disabled.';
            }
        } catch (error) {
            console.error('Error requesting notification permission:', error);
            notificationStatus.textContent = 'Permission denied or error occurred.';
        }
    });
});

2. Sending Targeted Push Notifications

Leverage Roost's API to send notifications to specific users or segments based on data you hold in your backend.

// Server-side (Node.js example)
const express = require('express');
const bodyParser = require('body-parser');
const app = express();
app.use(bodyParser.json());

// Assuming roostClient is initialized as in Setup
// const roostClient = new Roost.Client(...);

app.post('/api/send-notification', async (req, res) => {
    const { userId, title, body, url, imageUrl } = req.body;

    if (!userId || !title || !body) {
        return res.status(400).json({ error: 'Missing required fields: userId, title, body' });
    }

    try {
        const response = await roostClient.sendNotification({
            title: title,
            body: body,
            url: url || 'https://your-app.com', // Default URL
            icon: 'https://your-app.com/icon.png', // Optional icon
            image: imageUrl, // Optional large image for rich notifications
            target: {
                userId: userId // Target a specific user ID associated with Roost
            },
            data: { // Custom data accessible in the client-side service worker
                itemId: 'product_123',
                category: 'electronics'
            }
        });
        res.status(200).json({ success: true, messageId: response.messageId });
    } catch (error) {
        console.error('Error sending targeted notification:', error);
        res.status(500).json({ error: 'Failed to send notification' });
    }
});

// Example usage:
// fetch('/api/send-notification', {
//     method: 'POST',
//     headers: { 'Content-Type': 'application/json' },
//     body: JSON.stringify({
//         userId: 'some_authenticated_user_id',
//         title: 'New Message!',
//         body: 'You have a new message from a friend.',
//         url: 'https://your-app.com/messages/latest'
//     })
// });

3. Handling Notification Clicks and Custom Actions

When a user clicks a notification, your Roost-managed Service Worker can intercept this event. You can define what happens (e.g., open a specific URL or trigger custom client-side logic) directly in the notification payload.

// Server-side (Node.js example) for defining click actions
// This is part of the payload sent via roostClient.sendNotification()
const notificationPayload = {
    title: 'Product Alert!',
    body: 'The item you wished for is now in stock!',
    url: 'https://your-app.com/product/xyz123', // This URL opens on click
    actions: [ // Optional: Define custom buttons within the notification
        {
            action: 'view-details',
            title: 'View Details',
            icon: 'https://your-app.com/icon-details.png'
        },
        {
            action: 'save-for-later',
            title: 'Save for Later',
            icon: 'https://your-app.com/icon-save.png'
        }
    ],
    data: { // Custom data passed to the service worker
        productId: 'xyz123',
        actionType: 'stock_alert'
    }
};

// ... call roostClient.sendNotification with this payload ...
// Client-side (in your Roost-managed Service Worker, e.g., roost-sw.js or a custom one)
// Roost often provides hooks or a way to extend its default service worker.
// This is a generic Web Push API service worker example, assuming Roost passes data.

self.addEventListener('notificationclick', (event) => {
    const clickedNotification = event.notification;
    const action = event.action; // ID of the clicked action button, or empty string for the notification body

    clickedNotification.close(); // Close the notification

    // Get custom data passed from your server
    const customData = clickedNotification.data;
    const urlToOpen = customData.url || clickedNotification.data.url || 'https://your-app.com/'; // Fallback

    if (action === 'view-details') {
        event.waitUntil(clients.openWindow(urlToOpen));
    } else if (action === 'save-for-later') {
        // Perform an action without opening a new window, e.g., update a server-side list
        console.log(`User saved product ${customData.productId} for later.`);
        // Example: send a fetch request to your backend
        event.waitUntil(
            fetch('/api/save-product', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({ userId: 'current_user_id', productId: customData.productId })
            })
        );
    } else {
        // Default action: open the URL associated with the notification body click
        event.waitUntil(clients.openWindow(urlToOpen));
    }
});

Best Practices

  • Contextual Permission Prompts: Ask for notification permission only when it makes sense and provides value to the user, e.g., after they complete a transaction or explicitly show interest in updates.
  • Personalize Messages: Use available user data (e.g., username, preferred language, recent activity) to make notifications highly relevant and engaging.
  • Deep Linking: Always include a url in your notification payload that directs users to the most relevant page within your application, improving user experience and conversion.
  • Segment Your Audience: Utilize Roost's tagging or user ID features to send targeted notifications to specific groups of users, avoiding spam and increasing relevance.
  • Optimize Notification Content: Keep titles concise and bodies informative. Use emojis sparingly for emphasis, and consider rich notification features like images for greater impact.
  • Monitor Analytics: Regularly check Roost's analytics dashboard for delivery rates, click-through rates, and unsubscribe rates. Use this data to refine your notification strategy.
  • Graceful Degradation: Ensure your application functions well even for users who deny notification permissions or use browsers that don't support web push.

Anti-Patterns

  • Prompting on Page Load. Asking for notification permission immediately upon a user's first visit is intrusive and often leads to denials; wait for user engagement before asking.
  • Spamming Users. Sending too many notifications, or notifications that lack value, quickly leads to user fatigue and unsubscribes; prioritize quality over quantity.
  • Generic Messages. Sending the same, untargeted message to all users reduces engagement and perceived relevance; personalize messages based on user data and behavior.
  • Ignoring Unsubscribe Events. Failing to track and respect user unsubscribe actions can harm your brand reputation and lead to frustration; ensure your system processes and acts on these events promptly.
  • Hardcoding API Keys Client-Side. Never embed your Roost API Secret (or any sensitive API key) directly into client-side code; always use a secure backend service to trigger notifications.

Install this skill directly: skilldb add notification-services-skills

Get CLI access →