Resuming a user’s progress after remarketing to them by email or SMS
This guide explains how to implement user session recovery when users access your application from a different device, typically through email or SMS remarketing campaigns.
To securely allow users to resume their session on a different device, you’ll need to:
Generate a Hashed Token, which is generated from the user’s Entry ID, an expiration timestamp, and a Secret Key.
Send users a secure URL that contains this Hashed Token, as well as the user’s Entry ID and the expiration timestamp.
When a user opens the URL, use the Hashed Token and other parameters to securely call the Embeddables API from the client, which will return the User Data.
Use this retrieved User Data to restore the user’s session.
To generate a Hashed Token and secure URL, you’ll need a Secret Key - contact Embeddables Support to get this Secret Key.Here’s how to generate the Hashed Token and secure URL:
Copy
Ask AI
// Required parametersconst secretKey = process.env.EMBEDDABLES_LOAD_ENTRY_SECRET_KEYconst entryId = "entry_aaabbbcccdddeeefff" // The ID of the user's entryconst expiresAt = "2025-01-01T00:00:00.000Z" // ISO format timestamp// Generate the hashconst stringToHash = `${secretKey}---${entryId}---${expiresAt}`const token = sha256(stringToHash, 'utf8', 'hex')// Construct the final URLconst url = `https://yourwebsite.com/flow?token=${token}&entry_id=${entryId}&expires_at=${expiresAt}`
Once the user clicks the generated URL, create a Action, triggered on Embeddable Load, with the following code to fetch and restore their session:
Copy
Ask AI
// @TODO: Replace these with your own valuesconst EMBEDDABLE_ID = '<EMBEDDABLE_ID>' // Your Embeddable IDconst TOKEN_URL_PARAM_KEY = 'token' // The URL parameter key for the Hashed Tokenconst ENTRY_ID_URL_PARAM_KEY = 'entry_id' // The URL parameter key for the user's Entry IDconst EXPIRY_URL_PARAM_KEY = 'expires_at' // The URL parameter key for the expiration timestamp// All Actions must contain a function called output()function output(userData, helperFunctions, triggerContext) { // Grab the token from the URL const urlParams = (new URL(window.location)).searchParams const token = urlParams.get(TOKEN_URL_PARAM_KEY) const entryId = urlParams.get(ENTRY_ID_URL_PARAM_KEY) const expiresAt = urlParams.get(EXPIRY_URL_PARAM_KEY) // If we don't have all of token + entry ID + expiry date, // then stop here (this is a new user or the provided data is incomplete) if (!token || !entryId || !expiresAt) return // Fetch the User Data from the Embeddables API console.log('Retrieving User Data', { token }) fetch( "https://ierxexdtyashuotcsjyo.supabase.co/functions/v1/load_entry_data", { body: JSON.stringify({ flow_id: EMBEDDABLE_ID, entry_id: entryId, token, expires: expiresAt, }), headers: { "Content-Type": "application/json", }, method: "POST", } ).then(async (res) => { const data = await res.json(); console.log('Retrieved User Data: ', { data }) // If the User Data is successfully retrieved, // set the user data and navigate to the user's current page if (data && data.entry) { helperFunctions.setUserData({ ...data.entry }); window.Savvy.goToPage(EMBEDDABLE_ID, data.entry.current_page_key) } }).catch((err) => { console.error('Error Retrieving User Data:', { error }) })}