How to Manage Sessions with JavaScript in Release0 (with Code Snippets)
•
43 minutes read

Custom session management is now possible in Release0 embedded agents thanks to a powerful JavaScript-based Session Manager. This post walks through the usage of persistent and temporary sessions using localStorage
and sessionStorage
, and how to enable seamless cross-tab/session tracking — perfect for authentication flows.
🚀 What Is the Session Manager?
The Session Manager is a plug-and-play JavaScript snippet you can embed in your agent's <head>
via Advanced Settings > Custom head code.
It manages user data (like name and email) in either:
localStorage
: for persistent sessions across reloads and tabs (with optional expiry)sessionStorage
: for temporary sessions that expire when the tab or browser is closed
This approach avoids the limitations of cookies in iframe environments, which often face cross-origin restrictions.
🔗 Live Demo: Session Manager
Open your browser's DevTools to inspect how session data is stored and cleared.
(Press F12 on Windows/Linux or Cmd + Option + I on macOS)
🧠 Use Cases
✅ Authentication
You can store authenticated user data like email and role after login:
_10interface SessionData {_10 name: string;_10 email: string;_10 expiry: number;_10}_10_10const userData = AgentSessionManager.readSession('persistentUserSession') as SessionData | null;_10if (userData) return userData;_10return '';
Later, retrieve it:
_10{{=JSON.parse({{persistentUserData}}).name=}}
🔒 Temp Chat Sessions
Perfect for storing session-specific data, e.g. survey state:
_10AgentSessionManager.createTempSession('chatFlow', 'Temporary User', 'temp@demo.com');
🔄 Update or Delete
_10AgentSessionManager.updateSession('userAuth', 'Lisa R.', 'lisa.new@example.com');_10AgentSessionManager.deleteSession('userAuth');
📬 Message to Parent Site
If your R0 agent is embedded via iframe, send session data to the parent app:
_10AgentSessionManager.sendToParent('userAuth', 'SESSION_DATA');
💡 Best Practices
- Use persistent sessions for login/auth use cases
- Use temporary sessions for contextual interactions
- Set a default expiry (
DEFAULT_EXPIRY_DAYS
) in the script or customize per session - Sanitize user input before storing
- Use
getAllSessions()
for analytics/debugging - Monitor operations using the console for debugging and user flow analysis
- Implement postMessage communication for iframe-embedded agents
- If you're using TypeScript, define a proper interface for session data to avoid runtime errors.
Avoid storing sensitive tokens or passwords in local/session storage without encryption.
Tip: If you want to encrypt session data before storing it, consider using libraries like crypto-js
(AES).
🧪 Example Agent with Session Logic
Try this embedded agent to see session logic in action:
Open your browser's DevTools and navigate to Application > Storage to inspect stored session values.
(Shortcut: F12 on Windows/Linux or Cmd + Option + I on macOS)
This approach lets you bypass cookie limitations and build advanced stateful flows — even in restrictive iframe environments.
Let us know how you’re using session logic in your projects!
🛠️ How to Integrate It
To enable session tracking in your embedded agent, you'll need to install and configure the Session Manager script using the steps below.
1. Paste the Script
Go to your agent’s Advanced Settings > Custom head code, and insert the full script inside:
Click to reveal the full Session Manager script
_596<script id="agent-session-manager">_596_596'use strict';_596/**_596 * Agent Session Manager_596 * @description Session management utilities for embedded agent environments using localStorage/sessionStorage_596 * @version 1.0_596 * @author Chris HK_596 */_596_596/**_596 * Session Manager for iframe environments_596 * Uses localStorage and sessionStorage instead of cookies to avoid cross-origin restrictions_596 */_596const AgentSessionManager = {_596 _596 /**_596 * Configuration constants_596 */_596 CONFIG: {_596 SESSION_PREFIX: 'agent_session_',_596 DEFAULT_EXPIRY_DAYS: 1,_596 LOG_PREFIX: '[AgentSession]'_596 },_596_596 /**_596 * Utility functions_596 */_596 utils: {_596 /**_596 * Safe logging with prefix_596 * @param {string} level - log level (log, warn, error)_596 * @param {string} message - message to log_596 */_596 log: function(level, message) {_596 if (typeof console !== 'undefined' && console[level]) {_596 console[level](AgentSessionManager.CONFIG.LOG_PREFIX + ' ' + message);_596 }_596 },_596_596 /**_596 * Validate email format_596 * @param {string} email - email to validate_596 * @returns {boolean} - true if valid email format_596 */_596 isValidEmail: function(email) {_596 const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;_596 return typeof email === 'string' && emailRegex.test(email);_596 },_596_596 /**_596 * Check if localStorage is available_596 * @returns {boolean} - true if localStorage is available_596 */_596 isLocalStorageAvailable: function() {_596 try {_596 const test = '__localStorage_test__';_596 localStorage.setItem(test, test);_596 localStorage.removeItem(test);_596 return true;_596 } catch (e) {_596 return false;_596 }_596 },_596_596 /**_596 * Check if sessionStorage is available_596 * @returns {boolean} - true if sessionStorage is available_596 */_596 isSessionStorageAvailable: function() {_596 try {_596 const test = '__sessionStorage_test__';_596 sessionStorage.setItem(test, test);_596 sessionStorage.removeItem(test);_596 return true;_596 } catch (e) {_596 return false;_596 }_596 },_596_596 /**_596 * Create expiration timestamp_596 * @param {number} days - number of days from now_596 * @returns {number} - timestamp_596 */_596 createExpiryTimestamp: function(days) {_596 return Date.now() + (days * 24 * 60 * 60 * 1000);_596 },_596_596 /**_596 * Check if data has expired_596 * @param {number} expiryTimestamp - expiry timestamp_596 * @returns {boolean} - true if expired_596 */_596 isExpired: function(expiryTimestamp) {_596 return Date.now() > expiryTimestamp;_596 }_596 },_596_596 /**_596 * Create a session with user data (persistent storage)_596 * @param {string} sessionName - name of the session_596 * @param {string} userName - user name_596 * @param {string} userEmail - user email_596 * @param {number} expiryDays - expiry in days_596 * @returns {boolean} - true if session created successfully_596 */_596 createSession: function(sessionName, userName, userEmail, expiryDays = this.CONFIG.DEFAULT_EXPIRY_DAYS) {_596 try {_596 // Parameter validation_596 if (!sessionName || !userName || !userEmail) {_596 this.utils.log('error', 'All parameters are required: sessionName, userName, userEmail');_596 return false;_596 }_596_596 // Email validation_596 if (!this.utils.isValidEmail(userEmail)) {_596 this.utils.log('error', 'Invalid email format: ' + userEmail);_596 return false;_596 }_596_596 // Check localStorage availability_596 if (!this.utils.isLocalStorageAvailable()) {_596 this.utils.log('error', 'localStorage is not available');_596 return false;_596 }_596_596 // Create session data_596 const sessionData = {_596 name: userName,_596 email: userEmail,_596 created: new Date().toISOString(),_596 expires: this.utils.createExpiryTimestamp(expiryDays)_596 };_596_596 // Store in localStorage with prefix_596 const key = this.CONFIG.SESSION_PREFIX + sessionName;_596 localStorage.setItem(key, JSON.stringify(sessionData));_596_596 this.utils.log('log', 'Persistent session created successfully: ' + sessionName);_596 return true;_596_596 } catch (error) {_596 this.utils.log('error', 'Error creating session: ' + error.message);_596 return false;_596 }_596 },_596_596 /**_596 * Create a temporary session (session storage - expires when tab closes)_596 * @param {string} sessionName - name of the session_596 * @param {string} userName - user name_596 * @param {string} userEmail - user email_596 * @returns {boolean} - true if session created successfully_596 */_596 createTempSession: function(sessionName, userName, userEmail) {_596 try {_596 // Parameter validation_596 if (!sessionName || !userName || !userEmail) {_596 this.utils.log('error', 'All parameters are required: sessionName, userName, userEmail');_596 return false;_596 }_596_596 // Email validation_596 if (!this.utils.isValidEmail(userEmail)) {_596 this.utils.log('error', 'Invalid email format: ' + userEmail);_596 return false;_596 }_596_596 // Check sessionStorage availability_596 if (!this.utils.isSessionStorageAvailable()) {_596 this.utils.log('error', 'sessionStorage is not available');_596 return false;_596 }_596_596 // Create session data_596 const sessionData = {_596 name: userName,_596 email: userEmail,_596 created: new Date().toISOString(),_596 temporary: true_596 };_596_596 // Store in sessionStorage with prefix_596 const key = this.CONFIG.SESSION_PREFIX + sessionName;_596 sessionStorage.setItem(key, JSON.stringify(sessionData));_596_596 this.utils.log('log', 'Temporary session created successfully: ' + sessionName);_596 return true;_596_596 } catch (error) {_596 this.utils.log('error', 'Error creating temporary session: ' + error.message);_596 return false;_596 }_596 },_596_596 /**_596 * Read a session (checks both persistent and temporary storage)_596 * @param {string} sessionName - name of the session to read_596 * @returns {Object|null} - session data or null if not found/expired_596 */_596 readSession: function(sessionName) {_596 try {_596 if (!sessionName) {_596 this.utils.log('error', 'Session name is required');_596 return null;_596 }_596_596 // Try persistent storage first_596 const persistentKey = this.CONFIG.SESSION_PREFIX + sessionName;_596 if (this.utils.isLocalStorageAvailable()) {_596 const persistentData = localStorage.getItem(persistentKey);_596 if (persistentData) {_596 try {_596 const sessionData = JSON.parse(persistentData);_596 _596 // Check if expired_596 if (sessionData.expires && this.utils.isExpired(sessionData.expires)) {_596 this.utils.log('log', 'Persistent session expired, removing: ' + sessionName);_596 localStorage.removeItem(persistentKey);_596 return null;_596 }_596_596 this.utils.log('log', 'Persistent session read successfully: ' + sessionName);_596 return sessionData;_596 } catch (parseError) {_596 this.utils.log('error', 'Error parsing persistent session data: ' + parseError.message);_596 }_596 }_596 }_596_596 // Try temporary storage_596 const tempKey = this.CONFIG.SESSION_PREFIX + sessionName;_596 if (this.utils.isSessionStorageAvailable()) {_596 const tempData = sessionStorage.getItem(tempKey);_596 if (tempData) {_596 try {_596 const sessionData = JSON.parse(tempData);_596 this.utils.log('log', 'Temporary session read successfully: ' + sessionName);_596 return sessionData;_596 } catch (parseError) {_596 this.utils.log('error', 'Error parsing temporary session data: ' + parseError.message);_596 }_596 }_596 }_596_596 this.utils.log('log', 'Session not found: ' + sessionName);_596 return null;_596_596 } catch (error) {_596 this.utils.log('error', 'Error reading session: ' + error.message);_596 return null;_596 }_596 },_596_596 /**_596 * Update an existing session_596 * @param {string} sessionName - name of the session to update_596 * @param {string} userName - new user name_596 * @param {string} userEmail - new user email_596 * @returns {boolean} - true if session updated successfully_596 */_596 updateSession: function(sessionName, userName, userEmail) {_596 try {_596 // Parameter validation_596 if (!sessionName || !userName || !userEmail) {_596 this.utils.log('error', 'All parameters are required: sessionName, userName, userEmail');_596 return false;_596 }_596_596 // Email validation_596 if (!this.utils.isValidEmail(userEmail)) {_596 this.utils.log('error', 'Invalid email format: ' + userEmail);_596 return false;_596 }_596_596 // Check if session exists_596 const existingSession = this.readSession(sessionName);_596 if (!existingSession) {_596 this.utils.log('error', 'Session not found, cannot update: ' + sessionName);_596 return false;_596 }_596_596 // Determine storage type and update_596 if (existingSession.temporary) {_596 // Update temporary session_596 const sessionData = {_596 name: userName,_596 email: userEmail,_596 created: existingSession.created,_596 updated: new Date().toISOString(),_596 temporary: true_596 };_596_596 const key = this.CONFIG.SESSION_PREFIX + sessionName;_596 sessionStorage.setItem(key, JSON.stringify(sessionData));_596 this.utils.log('log', 'Temporary session updated successfully: ' + sessionName);_596 } else {_596 // Update persistent session_596 const sessionData = {_596 name: userName,_596 email: userEmail,_596 created: existingSession.created,_596 updated: new Date().toISOString(),_596 expires: existingSession.expires_596 };_596_596 const key = this.CONFIG.SESSION_PREFIX + sessionName;_596 localStorage.setItem(key, JSON.stringify(sessionData));_596 this.utils.log('log', 'Persistent session updated successfully: ' + sessionName);_596 }_596_596 return true;_596_596 } catch (error) {_596 this.utils.log('error', 'Error updating session: ' + error.message);_596 return false;_596 }_596 },_596_596 /**_596 * Delete a session (removes from both storages)_596 * @param {string} sessionName - name of the session to delete_596 * @returns {boolean} - true if session deleted successfully_596 */_596 deleteSession: function(sessionName) {_596 try {_596 if (!sessionName) {_596 this.utils.log('error', 'Session name is required');_596 return false;_596 }_596_596 let deleted = false;_596_596 // Remove from localStorage_596 if (this.utils.isLocalStorageAvailable()) {_596 const persistentKey = this.CONFIG.SESSION_PREFIX + sessionName;_596 if (localStorage.getItem(persistentKey)) {_596 localStorage.removeItem(persistentKey);_596 deleted = true;_596 }_596 }_596_596 // Remove from sessionStorage_596 if (this.utils.isSessionStorageAvailable()) {_596 const tempKey = this.CONFIG.SESSION_PREFIX + sessionName;_596 if (sessionStorage.getItem(tempKey)) {_596 sessionStorage.removeItem(tempKey);_596 deleted = true;_596 }_596 }_596_596 if (deleted) {_596 this.utils.log('log', 'Session deleted successfully: ' + sessionName);_596 return true;_596 } else {_596 this.utils.log('log', 'Session not found for deletion: ' + sessionName);_596 return false;_596 }_596_596 } catch (error) {_596 this.utils.log('error', 'Error deleting session: ' + error.message);_596 return false;_596 }_596 },_596_596 /**_596 * Clear all sessions (both persistent and temporary)_596 * @returns {boolean} - true if sessions cleared successfully_596 */_596 clearAllSessions: function() {_596 try {_596 let cleared = false;_596_596 // Clear from localStorage_596 if (this.utils.isLocalStorageAvailable()) {_596 const keys = Object.keys(localStorage);_596 keys.forEach(key => {_596 if (key.startsWith(this.CONFIG.SESSION_PREFIX)) {_596 localStorage.removeItem(key);_596 cleared = true;_596 }_596 });_596 }_596_596 // Clear from sessionStorage_596 if (this.utils.isSessionStorageAvailable()) {_596 const keys = Object.keys(sessionStorage);_596 keys.forEach(key => {_596 if (key.startsWith(this.CONFIG.SESSION_PREFIX)) {_596 sessionStorage.removeItem(key);_596 cleared = true;_596 }_596 });_596 }_596_596 if (cleared) {_596 this.utils.log('log', 'All sessions cleared successfully');_596 } else {_596 this.utils.log('log', 'No sessions found to clear');_596 }_596_596 return true;_596_596 } catch (error) {_596 this.utils.log('error', 'Error clearing sessions: ' + error.message);_596 return false;_596 }_596 },_596_596 /**_596 * Get all active sessions_596 * @returns {Array} - array of session objects_596 */_596 getAllSessions: function() {_596 const sessions = [];_596_596 try {_596 // Get persistent sessions_596 if (this.utils.isLocalStorageAvailable()) {_596 const keys = Object.keys(localStorage);_596 keys.forEach(key => {_596 if (key.startsWith(this.CONFIG.SESSION_PREFIX)) {_596 try {_596 const sessionData = JSON.parse(localStorage.getItem(key));_596 const sessionName = key.replace(this.CONFIG.SESSION_PREFIX, '');_596 _596 // Check if expired_596 if (!sessionData.expires || !this.utils.isExpired(sessionData.expires)) {_596 sessions.push({_596 name: sessionName,_596 data: sessionData,_596 type: 'persistent'_596 });_596 } else {_596 // Remove expired session_596 localStorage.removeItem(key);_596 }_596 } catch (parseError) {_596 this.utils.log('error', 'Error parsing session: ' + key);_596 }_596 }_596 });_596 }_596_596 // Get temporary sessions_596 if (this.utils.isSessionStorageAvailable()) {_596 const keys = Object.keys(sessionStorage);_596 keys.forEach(key => {_596 if (key.startsWith(this.CONFIG.SESSION_PREFIX)) {_596 try {_596 const sessionData = JSON.parse(sessionStorage.getItem(key));_596 const sessionName = key.replace(this.CONFIG.SESSION_PREFIX, '');_596 sessions.push({_596 name: sessionName,_596 data: sessionData,_596 type: 'temporary'_596 });_596 } catch (parseError) {_596 this.utils.log('error', 'Error parsing session: ' + key);_596 }_596 }_596 });_596 }_596_596 this.utils.log('log', 'Retrieved ' + sessions.length + ' active sessions');_596 return sessions;_596_596 } catch (error) {_596 this.utils.log('error', 'Error getting all sessions: ' + error.message);_596 return [];_596 }_596 },_596_596 /**_596 * Send session data to parent window via postMessage_596 * @param {string} sessionName - session name_596 * @param {string} messageType - type of message_596 * @returns {boolean} - true if message sent successfully_596 */_596 sendToParent: function(sessionName, messageType = 'SESSION_DATA') {_596 try {_596 if (window.parent === window) {_596 this.utils.log('warn', 'Not in iframe, cannot send to parent');_596 return false;_596 }_596_596 const sessionData = this.readSession(sessionName);_596 if (!sessionData) {_596 this.utils.log('error', 'Session not found for sending: ' + sessionName);_596 return false;_596 }_596_596 const message = {_596 type: messageType,_596 sessionName: sessionName,_596 sessionData: sessionData,_596 timestamp: new Date().toISOString()_596 };_596_596 window.parent.postMessage(message, '*');_596 this.utils.log('log', 'Session data sent to parent: ' + sessionName);_596 return true;_596_596 } catch (error) {_596 this.utils.log('error', 'Error sending to parent: ' + error.message);_596 return false;_596 }_596 }_596};_596_596// Usage Examples:_596/*_596// === Basic Usage ===_596_596// Create a persistent session (expires in 1 day by default)_596AgentSessionManager.createSession('userLogin', 'John Doe', 'john.doe@example.com');_596_596// Create a temporary session (expires when tab closes)_596AgentSessionManager.createTempSession('chatSession', 'Jane Smith', 'jane.smith@example.com');_596_596// Read a session_596const userData = AgentSessionManager.readSession('userLogin');_596if (userData) {_596 console.log('User Name:', userData.name);_596 console.log('User Email:', userData.email);_596 console.log('Created:', new Date(userData.created).toLocaleString());_596}_596_596// Update a session_596AgentSessionManager.updateSession('userLogin', 'John Smith', 'john.smith@example.com');_596_596// Delete a session_596AgentSessionManager.deleteSession('userLogin');_596_596// === Advanced Usage ===_596_596// Get all active sessions_596const allSessions = AgentSessionManager.getAllSessions();_596console.log('Active sessions:', allSessions);_596_596// Clear all sessions_596AgentSessionManager.clearAllSessions();_596_596// === Iframe Communication ===_596_596// Send session data to parent window_596AgentSessionManager.sendToParent('userLogin', 'USER_AUTHENTICATED');_596_596// Listen for messages from parent (in iframe)_596window.addEventListener('message', function(event) {_596 if (event.data.type === 'REQUEST_SESSION') {_596 AgentSessionManager.sendToParent(event.data.sessionName, 'SESSION_RESPONSE');_596 }_596});_596_596// === Error Handling Example ===_596_596// Create session with error handling_596if (AgentSessionManager.createSession('userSession', 'Test User', 'invalid-email')) {_596 console.log('Session created successfully');_596} else {_596 console.log('Failed to create session - check console for errors');_596}_596_596// === Custom Expiry Example ===_596_596// Create session with custom expiry (30 days)_596AgentSessionManager.createSession('longTermSession', 'VIP User', 'vip@example.com', 30);_596_596*/_596_596// Export for module usage (optional)_596if (typeof module !== 'undefined' && module.exports) {_596 module.exports = AgentSessionManager;_596}_596_596// Global assignment for direct usage_596if (typeof window !== 'undefined') {_596 window.AgentSessionManager = AgentSessionManager;_596}_596 _596</script>_596_596<script id="send-message-to-parent">_596// Send a session operation message to the parent page_596function sendSessionOperation(operation) {_596 const message = {_596 type: "agent",_596 message: operation_596 };_596 _596 // Send to parent window (if your agent is in an iframe)_596 window.parent.postMessage(message, '*');_596}_596</script>
2. Use the API in Your Agent
Once loaded, the script is globally accessible as AgentSessionManager
. Example:
_10AgentSessionManager.createSession('userLogin', 'Alex Blue', 'alex@example.com', 7);
Where:
'userLogin'
is the session key'Alex Blue'
is the user's name'alex@example.com'
is the user's email7
is the number of days until the session expires