UNPKG

@pubnub/mcp

Version:

PubNub Model Context Protocol MCP Server for Cursor and Claude

226 lines (177 loc) 8.71 kB
# PubNub Presence Best Practices > **🔑 Feature Enablement Required** > > To use Presence, you must enable it in your PubNub Admin Portal: > 1. Navigate to your keyset settings > 2. Enable the **Presence** add-on > 3. Choose **"Selected channels only (recommended)"** instead of "All channels" > 4. Configure specific channel rules in **Presence Management** > > Without enabling Presence and configuring channel rules, presence tracking will not work. This guide demonstrates best practices for implementing PubNub Presence functionality in JavaScript. The example shows how to build a real-time user counter that tracks how many users are currently connected to a channel. ## Configuration Prerequisites ### Enable Presence Management for Selected Channels Before implementing presence functionality, you must configure Presence in your PubNub Admin Dashboard. When setting up your keyset, you'll see presence configuration options: **Recommended Configuration:** - Select "**Selected channels only (recommended)**" instead of "All channels" - This prevents high costs and gives you control over which channels track presence - You'll configure specific channel rules later in Presence Management. Ensure you do not skip the extra Presence Management step, or presence will not work. **Why this matters:** Tracking presence on all channels can incur high costs and generate unnecessary events. Using "Selected channels only" allows you to: - Control costs by only tracking presence where needed - Reduce network overhead from unused presence events - Configure channel-specific presence rules in Presence Management **Note:** No presence transactions will be captured until you complete the channel configuration in Presence Management, even after enabling presence in your code. ## Best Practices Overview ### 1. Unique User Identification Always use a unique user ID for each user to ensure accurate presence tracking: **Why this is important:** Each client needs a unique identifier to be properly tracked in presence events. Without unique IDs, the system cannot distinguish between different users. ### 2. Enable Event Engine for Better Connection Management Use the Event Engine for improved connection reliability and automatic reconnection: ```javascript const pubnub = new PubNub({ publishKey: 'your-publish-key', subscribeKey: 'your-subscribe-key', userId: generateRandomUserId(), enableEventEngine: true // Best practice for connection management }); ``` **Why this is important:** The Event Engine provides automatic reconnection, better error handling, and more predictable connection states, which are crucial for reliable presence tracking. ### 3. Use Channel-Based Subscriptions with Presence Events Enable presence events specifically for channels that need user tracking: ```javascript const channel = pubnub.channel(channelName); const subscription = channel.subscription({ receivePresenceEvents: true // Enable presence event delivery }); ``` **Why this is important:** This approach gives you fine-grained control over which channels receive presence events, reducing unnecessary network traffic and processing. ### 4. Handle Presence Events Properly Listen for presence events to get real-time updates about user join/leave activities: ```javascript subscription.onPresence = (presenceEvent) => { console.log('Presence event:', presenceEvent); updateUserCount(presenceEvent.occupancy); // Update UI with current count }; ``` **Why this is important:** Presence events provide real-time notifications when users join or leave, giving you immediate updates without polling. ### 5. Get Initial Occupancy on Connection Always fetch the current occupancy when first connecting to avoid starting with stale data: ```javascript pubnub.addListener({ status: (statusEvent) => { if (statusEvent.category === 'PNConnectedCategory') { getInitialOccupancy(); // Get current count on connection } } }); async function getInitialOccupancy() { try { const result = await pubnub.hereNow({ channels: [channelName], includeUUIDs: false // Optimize by not fetching UUIDs if not needed }); const occupancy = result.channels[channelName] ? result.channels[channelName].occupancy : 0; updateUserCount(occupancy); } catch (error) { console.error('Error getting initial occupancy:', error); updateUserCount(0); // Fail gracefully with 0 count } } ``` **Why this is important:** Without getting initial occupancy, your counter might show 0 users even when people are already connected. This ensures accurate state from the start. ### 6. Optimize hereNow Calls Use `includeUUIDs: false` when you only need occupancy counts to reduce bandwidth: ```javascript const result = await pubnub.hereNow({ channels: [channelName], includeUUIDs: false // More efficient when you only need counts }); ``` **Why this is important:** Including UUIDs increases payload size and processing time. Only request them when you actually need the user identifiers. ### 7. Proper Cleanup Always unsubscribe when the user leaves to ensure accurate presence counts: ```javascript window.addEventListener('beforeunload', () => { subscription.unsubscribe(); // Clean exit ensures accurate presence }); ``` **Why this is important:** Without proper cleanup, the system may not immediately recognize that a user has left, leading to inflated occupancy counts. ## Complete Working Example ```html <div id="user-count">0</div> <script> // Generate a random userId function generateRandomUserId() { return 'user_' + Math.random().toString(36).substr(2, 9); } // Initialize PubNub with random userId const pubnub = new PubNub({ publishKey: 'pub-c-c4e46d96-bf76-423d-952a-b56e7b3f58c8', subscribeKey: 'sub-c-118cccb2-8546-11e8-9542-023dfa3e4dae', userId: generateRandomUserId(), enableEventEngine: true }); const channelName = 'presence-counter-channel-test'; const userCountElement = document.getElementById('user-count'); // Function to update the display with animation function updateUserCount(count) { userCountElement.textContent = count; userCountElement.classList.add('pulse'); setTimeout(() => { userCountElement.classList.remove('pulse'); }, 500); } // Create subscription with presence enabled const channel = pubnub.channel(channelName); const subscription = channel.subscription({ receivePresenceEvents: true }); // Add presence event listener subscription.onPresence = (presenceEvent) => { console.log('Presence event:', presenceEvent); updateUserCount(presenceEvent.occupancy); }; // Add general status listener pubnub.addListener({ status: (statusEvent) => { console.log('Status:', statusEvent.category); if (statusEvent.category === 'PNConnectedCategory') { console.log('Connected to PubNub'); // Get initial occupancy count getInitialOccupancy(); } } }); // Function to get initial occupancy async function getInitialOccupancy() { try { const result = await pubnub.hereNow({ channels: [channelName], includeUUIDs: false }); const occupancy = result.channels[channelName] ? result.channels[channelName].occupancy : 0; updateUserCount(occupancy); } catch (error) { console.error('Error getting initial occupancy:', error); updateUserCount(0); } } // Subscribe to the channel subscription.subscribe(); // Clean up on page unload window.addEventListener('beforeunload', () => { subscription.unsubscribe(); }); </script> ``` ## Key Takeaways 1. **Unique User IDs**: Always generate unique identifiers for accurate tracking 2. **Event Engine**: Enable for better connection management and reliability 3. **Targeted Subscriptions**: Only enable presence events where needed 4. **Initial State**: Always fetch current occupancy on connection 5. **Optimization**: Use `includeUUIDs: false` when only counting users 6. **Cleanup**: Properly unsubscribe to maintain accurate counts 7. **Error Handling**: Implement try-catch blocks and fallback values Following these practices ensures reliable, efficient, and accurate presence tracking in your PubNub applications.