> Portal Navigation:
>
> - Append `.md` to any URL under `https://dev.wix.com/docs/` to get its markdown version.
> - Pages are either content pages (article or reference text) or menu pages (a list of links to child pages).
> - To get a menu page, truncate any URL to a parent path and append `.md` (e.g. `https://dev.wix.com/docs/sdk.md`, `https://dev.wix.com/docs/sdk/core-modules.md`).
> - Top-level index of all portals: https://dev.wix.com/docs/llms.txt
> - Full concatenated docs: https://dev.wix.com/docs/llms-full.txt
## Resource: Handle Visitors Using the JS SDK
## Article: Handle Visitors
## Article Link: https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/visitors/handle-visitors-using-the-js-sdk.md
## Article Content:
# Handle Visitors with the JavaScript SDK
> **Note:** This article is only relevant for [self-managed headless projects](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/about-self-managed-headless.md). For [Wix-managed headless projects](https://dev.wix.com/docs/wix-cli/guides/about-the-wix-cli.md), the CLI automatically generates and manages visitor tokens for you.
Use visitor tokens to maintain anonymous visitor sessions in your self-managed headless project. The SDK uses these tokens when making requests to Wix APIs on behalf of a visitor, preserving their data such as cart items or event reservations.
## Step 1 | Create a client
Create a Wix client with the [OAuth strategy](https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md). Before creating the client, check your storage for tokens from a previous session:
- **Returning visitor:** Tokens exist in storage. Pass them to the client to resume the previous session.
- **New visitor:** No tokens found. Omit tokens when creating the client and generate new tokens as described in [Step 2](#step-2--generate-visitor-tokens).
```javascript
import { createClient, OAuthStrategy } from "@wix/sdk";
// Retrieve tokens from storage (see Step 3 for storage options)
const storedTokens = yourGetStoredTokensMethod();
const wixClient = createClient({
auth: OAuthStrategy({
clientId: "",
// Pass tokens if they exist, otherwise omit to start a new session.
tokens: storedTokens ?? undefined,
}),
});
```
> **Note:** OAuth for Wix Headless only requires a client ID. It doesn't require a client secret.
## Step 2 | Generate visitor tokens
Call [generateVisitorTokens()](https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md) and store tokens to persist the session.
- **Returning visitor:** Visitor tokens expire after 4 hours, so you must ensure the stored tokens are still valid. The method returns the same tokens if they're still valid, or renewed tokens if they've expired.
- **New visitor:** The method creates tokens for a new session. Alternatively, the client creates them automatically on your first [API call](#step-4--make-api-calls). Calling `generateVisitorTokens()` initially lets you persist tokens if the app reloads before making your first API call.
```javascript
//storedTokens are undefined for new visitors
const tokens = await wixClient.auth.generateVisitorTokens(storedTokens);
yourStoreTokensMethod(tokens); // See Step 3 for implementation options
```
## Step 3 | Save tokens to persist the session
To persist a visitor's session across page reloads or app restarts, save the tokens to local storage, a cookie, or a file.
Retrieve the active tokens with [getTokens()](https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md).
```javascript
const tokens = wixClient.auth.getTokens();
```
The method returns an object in this format:
```javascript
{
accessToken: {
value: "OauthNG.JWS.eyJraWQiOi...3NbrhrauQ",
expiresAt: 1677581109
},
refreshToken: {
value: "JWS.eyJraWQiOiJZSEJzdUpwSCIsImFsZyI6IkhTMjU2In0.eyJkYXRhIjoiXCJkMDY4OTM4OS1kNTExLTRlYWMtYThjZC03MWQwMzA1NGIxM2NcIiIsImlhdCI6MTY3NzU2NjcwOSwiZXhwIjoxNzA5MTAyNzA5fQ.w2D7wECX_T-XfRzP4pXSoH8XSdHFBPnKx50FYzftRdc",
role: "visitor"
}
}
```
Save the tokens to your preferred storage:
```javascript
// Browser: Save to localStorage
localStorage.setItem("wixSession", JSON.stringify(tokens));
// Browser: Save to a cookie
document.cookie = `wixSession=${encodeURIComponent(JSON.stringify(tokens))}; path=/; max-age=31536000`;
// Server-side: Save to your session store or database
// The implementation depends on your stack (for example, Redis, a database, or your framework's session layer).
await saveTokensToSession(userId, tokens);
```
## Step 4 | Make API calls
Call Wix API methods using your client.
> **Note:** If you create the client without tokens or skip [Step 2](#step-2--generate-visitor-tokens), the client generates tokens automatically on your first API call. Make sure to retrieve and save the tokens as described in [Step 3](#step-3--save-tokens-to-persist-the-session).
```javascript
// Make API calls
const { products } = await wixClient.productsV3.searchProducts({
filter: { name: { $startsWith: "shoes" } },
cursorPaging: { limit: 4 },
});
// The visitor's cart is preserved across sessions
const cart = await wixClient.currentCart.getCurrentCart();
```
## Example
The following example shows the complete visitor session flow, from creating a client to making API calls:
```javascript
import { createClient, OAuthStrategy } from "@wix/sdk";
import { currentCart } from "@wix/ecom";
import { productsV3 } from "@wix/stores";
// Retrieve tokens from a previous session, if they exist
const storedTokens = localStorage.getItem("wixSession")
? JSON.parse(localStorage.getItem("wixSession"))
: undefined;
// Create a client - resume the previous session if tokens exist, or start a new one
const wixClient = createClient({
modules: { currentCart, productsV3 },
auth: OAuthStrategy({
clientId: "",
tokens: storedTokens ?? undefined,
}),
});
// Generate, validate, or renew visitor tokens
const tokens = await wixClient.auth.generateVisitorTokens(storedTokens);
//Store tokens to persist the current session
localStorage.setItem("wixSession", JSON.stringify(tokens));
// Make API calls
const { products } = await wixClient.productsV3.searchProducts({
filter: { name: { $startsWith: "shoes" } },
cursorPaging: { limit: 4 },
});
// The visitor's cart is preserved across sessions
const cart = await wixClient.currentCart.getCurrentCart();
```
## Manage tokens manually
In most cases, the client manages tokens automatically. Use these methods when you need manual control.
### Set tokens on an existing client
If you already have a client instance and need to set tokens on it later, use [setTokens()](https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md):
```javascript
const savedTokens = JSON.parse(localStorage.getItem("wixSession"));
wixClient.auth.setTokens(savedTokens);
```
Once tokens are set, the visitor's data is preserved. For example, items added to a cart or tickets reserved are reflected in future API calls.
### Generate tokens explicitly
Call [generateVisitorTokens()](https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md) to create tokens before making any API calls:
```javascript
const tokens = await wixClient.auth.generateVisitorTokens();
```
### Validate or renew existing tokens
Pass existing tokens to `generateVisitorTokens()` to confirm they're valid or renew them if expired:
```javascript
const refreshedTokens = await wixClient.auth.generateVisitorTokens(existingTokens);
```
The method returns:
- The same tokens if the access token is still valid.
- A new access token if the access token expired but the refresh token is valid.
- New access and refresh tokens if the refresh token is invalid.
### Force token renewal
Use [renewToken()](https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md) to generate a new access token without checking if the current one is valid:
```javascript
const tokens = wixClient.auth.getTokens();
const newTokens = await wixClient.auth.renewToken(tokens.refreshToken);
```
### Check login status
Use [loggedIn()](https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md) to check if the current visitor is a logged-in member:
```javascript
const isLoggedIn = wixClient.auth.loggedIn();
// Returns false for anonymous visitors, true for logged-in members
```
## See also
- [About Handling Visitors](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/visitors/about-handling-visitors.md)
- [OAuthStrategy API Reference](https://dev.wix.com/docs/sdk/core-modules/sdk/oauth-strategy.md)
- [Handle Members with a Custom Login Page](https://dev.wix.com/docs/go-headless/develop-your-project/self-managed-headless/authentication/members/custom-login-page/custom-login/custom-login-using-the-js-sdk.md)