The old out of the box version of webchat used to remember a user across sessions when accessed through the same browser. I assume this was through the use of cookies? The new version ("gemini") does not do this. Every time I close the browser window and open again from the same browser, a new ID is sent, thus I no longer have access to saved userState information. To reclaim formatting, I switched over to botframework-webchat via directline and have the same issue. There is an explicit input for userID, and I have no idea how to make this consistent for a particular user.
I am not a web developer and have no need at this time to make this a robust implementation. I simply want to make this work the same way the former out of the box webchat worked. Can anyone shed some light on how that previous version worked, and/or how I can make the directline version have the same functionality?
Edit: Based on Steven's comment to the answer below, I tried to implement get/set cookies, but it is not working. Below is the code I tried. I can see through console that I am getting in to the if statement and userID is being generated, but it's not getting saved (I don't see it in Application>Storage>Cookies so it's not just the get not working). Please advise!
function setCookie(name,value,days) {
var expires = "";
if (days) {
var date = new Date();
date.setTime(date.getTime() + (days*24*60*60*1000));
expires = "; expires=" + date.toUTCString();
}
document.cookie = name + "=" + (value || "") + expires + "; path=/";
}
function getCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
function eraseCookie(name) {
document.cookie = name+'=; Max-Age=-99999999;';
}
if (!getCookie('userID')) {
console.log('in if');
var userID = Date.now() + '_' + Math.random().toString().substr(2, 9);
console.log(userID);
setCookie('userID',userID,999);
}
console.log('out of if');
Ultimately I found that the way to handle this was by initiating the chat session via token. When you provide a user
property in the body of the token request, it will properly initiate the session and pull up the correct user state (if user has conversed with the bot before). The documentation on initiating webchat via token is a little light. Here's how I did it.
First, you need to create an endpoint in your bot to generate the token (I'm passing in userId from browser, which you'll see in a minute).
server.post('/directline/token', async (req, res) => {
try {
var body = {User:{Id:req.body.userId}};
const response = await request({
url: 'https://directline.botframework.com/v3/directline/tokens/generate',
method: 'POST',
headers: { Authorization: `Bearer ${process.env.DIRECTLINE_SECRET}`},
json: body,
rejectUnauthorized: false
});
const token = response.token;
res.setHeader('Content-Type', 'text/plain');
res.writeHead(200);
res.write(token);
res.end();
} catch(err) {
console.log(err);
res.setHeader('Content-Type', 'text/plain');
res.writeHead(500);
res.write('Call to retrieve token from Direct Line failed');
res.end();
}
})
You could return JSON here, but I chose to return token only as text. Now to call the function, you'll need to hit this endpoint from the script wherever you are deploying the bot (this is assuming you are using botframework-webchat CDN). Here is the code I used for that.
const response = await fetch('https://YOURAPPSERVICE.azurewebsites.net/directline/token', {
method: 'POST',
headers: {'Content-Type':'application/json'},
body: JSON.stringify({userId:userID})
});
const token = await response.text();
Body of request must be stringified JSON. Fetch
returns the response as a stream, so you need to convert it using .text()
or .json()
depending on how you are sending the response from your bot endpoint (I used .text()
). You need to await both the fetch
AND the response.text()
. My whole script to deploy the webchat is within an async function.
Combined with the cookie implementation mentioned above for setting and recalling the userID, this allowed me to remember the user as long as they still have the cookie in their browser. Note that this will work only for Directline. If you are using the OOTB webchat it no longer remembers you. I would say in its current implementation the OOTB webchat is suited only for testing and I wouldn't recommend using it in any production capacity.