Widget B2B — history on other devices
This section covers restoring the widget’s personal history when the same person opens the site from another browser or device.
The site must authenticate the person. Its backend obtains and privately stores the restore credential for that user and that widget. The browser passes it to init() together with the profile.
For the script alone, or to prefill profile and company while staying in a guest session, see Widget B2C. restore_id endpoints, persistence, and concurrency: Technical integration.
What it adds compared with the guest session
| Guest | Restore | |
|---|---|---|
| Login on the site | Not required | Required, because the credential comes from your backend |
| Data that identifies the chat | Browser guest credential, or profile passed to init() |
external_user_id and restore_id together |
| Continuity | Same browser | Different browsers and devices, on the authorized widget channel |
| Who issues the credential | Loader | Site backend, through Quoting24 |
name, phone, email, external_id, company_name, and external_user_id, by themselves, do not restore history. external_user_id without restore_id is not enough. The field is restore_id, in snake case: restoreId is not a loader field.
Restore does not merge old guest sessions and does not share history among colleagues of the same company. It applies only to the widget channel.
You can send the company fields in the same init(). Association or creation follows the rules of the guest payload: it is independent of restore and does not prove identity.
Flow
- The customer logs in on the portal
- The authenticated backend asks Quoting24 for a credential (
provisionRestoreId) or reuses the one already saved - The page calls
init()with the sameexternal_user_id, therestore_id, and, if needed, the company data - Quoting24 checks the credential and shows the widget conversations visible for that person, including closed ones
- On logout, or on a person change, the page calls
reset()so the previous chat does not stay in the browser
widget.init({
external_id: "52",
company_name: "Ricambi Stella S.r.l.",
name: "Mario Rossi",
phone: "+393331234567",
email: "mario.rossi@ricambi-stella.example",
external_user_id: "1042",
restore_id: session.restore_id,
});
restore_id is the backend response for the authenticated user. Use it without modifying it. Maximum 200 characters. It requires the matching external_user_id: a stable ID of the single person, non-empty, maximum 100 characters after trim. It is not a shared company ID.
external_id is compared with web_code. Together with company_name it can create the missing company. It does not authenticate the user and it does not replace restore_id.
Prerequisites
In addition to branding, domains, and embed code:
- a backend integration authorized in Quoting24
- the private integration secret, on the server only
- a provisioning endpoint, usually
widget.provisionRestoreId - a private store in the site database, one credential per user and widget
The public key in the script URL and the integration secret are different values. See Overview.
Endpoint on the site backend
/api/widget/session is an example to implement in the portal. It is not a public Quoting24 URL.
{
"external_user_id": "1042",
"external_id": "52",
"company_name": "Ricambi Stella S.r.l.",
"name": "Mario Rossi",
"phone": "+393331234567",
"email": "mario.rossi@ricambi-stella.example",
"restore_id": "<credential-returned-by-quoting24>"
}
- Identity comes from the server session, not from an ID chosen by the browser
Cache-Control: no-store- Do not log or cache
restore_id - Do not put secrets in the script URL or in public
data-*attributes - Save the credential before returning it to the browser
The contract toward Quoting24 (attempt_id, saved_restore_id, lock, key reuse) is in Technical integration.
If the portal already has an authenticated endpoint that, for the current user, returns this widget’s restore_id, use that response. Combine it with the person ID and the company reference in the init() call.
Login, reload, account change, logout
Distinguish a page reload from a real person or account change.
- Reload with the same login still active:
init()withoutreset(), so the saved guest session remains if you are only supplying the profile again. With restore, reuse the credential already persisted: do not generate a new one on every page view - Person change, account change, logout:
reset()immediately, then the new profile, or noinit()if the user has left - Discard restore responses that arrive after the change: an old response must not be treated as a new login
- In a SPA keep a single instance in the main layout. A route change does not run provisioning again
If restore is unavailable you can offer the guest chat: reset(), then init() without restore_id. That chat stays separate from the restored history.
A credential that is invalid, belongs to another user, or has been revoked is rejected. Quoting24 does not turn it into a guest session. The widget’s «Riprova» button does not by itself ask your backend for a new restore_id. The current interface is in Italian, so that button label is Italian.
Example of applyWidgetAuth and unmount: Technical integration.
reset() forgets this instance’s guest session and the credential saved in the browser. It does not revoke restore_id on the server and does not close sessions on other devices. The site must update the other open tabs.
Previous conversations
In the restored history, closed chats can appear as a previous conversation.
- Opening them for reading does not reopen the old conversation
- New messages stay on the active conversation
Checklist before release
- [ ] Integration secret on the server only
- [ ]
external_user_idstable and per person, identical between provisioning andinit() - [ ]
restore_idpersisted before the response to the browser, and reused on later visits - [ ] Same user on a second browser: same history
- [ ] Two users of the same company: distinct histories
- [ ]
external_idandcompany_namechecked in the registry, without expecting them to restore the chat - [ ] Logout or account change during the fetch: no chat of the previous user left on screen
- [ ] Guest ↔ restore transition with
reset()in between - [ ] Revoked or invalid credential: error, with no silent fallback to guest
Tests and symptoms: Verify the integration · Troubleshooting.