Identify the App Instance in a Self-Hosted Site Widget

For security reasons, app instance ID (instanceId) isn’t directly accessible in site widgets or settings panels. Instead, you can securely extract it by sending a Wix access token to a backend API. The backend can decode the token, get the instance ID or instance data, and perform any necessary business logic.

This article explains how to:

  • Backend: Expose a backend API to identify the app instance.
  • Frontend: Pass a Wix access token from your custom element to your backend.

Step 1 | Expose a backend API

To securely identify the app instance:

  1. Expose a backend API. You can build and deploy your backend API using any framework. The examples in this article are based on a Node.js server.

  2. In your backend API code, get the Wix access token from the authorization header.

    Copy
    const accessToken = req.headers["authorization"];
  3. Depending on your use case, you may only need instanceId or you may need more detailed app instance data.

    • To extract instanceId:

      Call Get Token Info to extract instanceId from the access token.

    Copy
    const tokenResponse = await axios.post( "https://www.wixapis.com/oauth2/token-info", { token: accessToken, }, ); const instanceId = tokenResponse.data.instanceId;
    • To fetch instance data:

      Elevate the access token to an app identity. Then, call Get App Instance (SDK | REST). Elevation is necessary because access tokens sent from site widgets are tied to a site visitor or member identity, which don't have access to instance data.

      The method of performing elevation varies depending on whether you're using the JavaScript SDK or REST API.

      JavaScript SDK

      Copy
      const elevatedClient = createClient({ auth: await AppStrategy({ appId: "<YOUR_APP_ID>", appSecret: "<YOUR_APP_SECRET>", accessToken: accessToken, }).elevated(), modules: { appInstances, }, }); const instanceResponse = await elevatedClient.appInstances.getAppInstance();

      To learn more, see Elevate SDK Call Permissions with Self-Hosting.

      REST API

    Copy
    // Extract the app instance ID from the access token const tokenResponse = await axios.post( "https://www.wixapis.com/oauth2/token-info", { token: accessToken, }, ); const instanceId = tokenResponse.data.instanceId; // Create a new access token with an app identity const newTokenResponse = await axios.post( "https://www.wixapis.com/oauth2/token", { grant_type: "client_credentials", client_id: "<YOUR_APP_ID>", client_secret: "<YOUR_APP_SECRET>", instanceId: instanceId, }, ); const elevatedAccessToken = newTokenResponse.data.access_token; // Use the new token to get instance data const instanceResponse = await axios.get( "https://www.wixapis.com/apps/v1/instance", { headers: { Authorization: `Bearer ${elevatedAccessToken}`, }, }, );

    To learn more, see Elevate REST API Call Permissions with Self-Hosting.

Step 2 | Pass a Wix access token to your backend

To pass a Wix access token from your custom element to your backend:

  1. Add a self-hosted site widget extension with a custom element. If you already have a site widget, skip to the next step.

  2. In your custom element code, initialize a WixClient with the site authentication and host configuration.

    Copy
    const myWixClient = createClient({ auth: site.auth(), host: site.host({ applicationId: "<YOUR_APP_ID>" }), });
  3. Add the following line to the constructor of your custom element class to inject the Wix access token.

    Copy
    this.accessTokenListener = myWixClient.auth.getAccessTokenInjector();
  4. Import the httpClient submodule from the Essentials SDK.

    Copy
    import { httpClient } from "@wix/essentials";
  5. Call fetchWithAuth() to send the access token to your backend.

    Copy
    const response = await myWixClient.fetchWithAuth("<YOUR_API_URL>");

Tip: To get instanceId in the settings panel, initialize a WixClient with the editor authentication and host configuration. Then, call fetchWithAuth().

Examples

Depending on your use case, the logic of your backend API will vary. For example, you may only need to extract instanceId and then use it to make a request to your own database. Alternatively, you may wish to request app instance data from Wix, in which case you'd need to elevate your access token.

See the relevant example for your use case:

Backend: Extract instanceId

The following example creates a Node.js Express API called get-instance. The API extracts instanceId from the access token provided by the frontend request.

Copy
import express from "express"; import axios from "axios"; import cors from "cors"; const app = express(); const port = 5000; app.use(cors()); // Edit this code based on your business logic const mockDatabaseQuery = async (instanceId) => { console.log(`Mock database query with instance ID: ${instanceId}`); if (instanceId) { return { status: "Success", }; } else { return { status: "No instance ID.", }; } }; // Define a backend API app.get("/get-instance", async (req, res) => { try { // Get the Wix access token from the `authorization` header const accessToken = req.headers["authorization"]; if (!accessToken) { throw new Error("Access token is required."); } // Extract the app instance ID from the access token const tokenData = await axios.post( "https://www.wixapis.com/oauth2/token-info", { token: accessToken, }, ); const instanceId = tokenData.data.instanceId; console.log("Instance ID:", instanceId); // Edit this code based on your business logic const data = await mockDatabaseQuery(instanceId); return res.json(data); } catch (error) { console.error("Error processing request:", error.message); return res.status(500).json({ error: "Failed to process request" }); } }); app.listen(port, () => { console.log(`Server running at http://localhost:${port}`); });

Backend: Fetch instance data with the JavaScript SDK

The following example creates a Node.js Express API called get-instance. The API receives an access token from the frontend, creates a client with elevated permissions, and then uses the elevated client to fetch the app instance data.

Copy
import express from "express"; import cors from "cors"; import { createClient, AppStrategy } from "@wix/sdk"; import { appInstances } from "@wix/app-management"; const app = express(); const port = 5000; app.use(cors()); // Define a backend API app.get("/get-instance", async (req, res) => { try { // Get the Wix access token from the `authorization` header const accessToken = req.headers["authorization"]; if (!accessToken) { throw new Error("Access token is required."); } const elevatedClient = createClient({ auth: await AppStrategy({ appId: "<YOUR_APP_ID>", appSecret: "<YOUR_APP_SECRET>", accessToken: accessToken, }).elevated(), modules: { appInstances, }, }); const instanceResponse = await elevatedClient.appInstances.getAppInstance(); return res.json(instanceResponse.data); } catch (error) { console.error("Error processing request:", error.message); return res.status(500).json({ error: "Failed to process request" }); } }); app.listen(port, () => { console.log(`Server running at http://localhost:${port}`); });

Backend: Fetch instance data with the REST API

The following example creates a Node.js Express API called get-instance. The API receives an access token from the frontend, uses the token to request a new access token with the permissions of an app, and then uses the new elevated access token to fetch the app instance data.

Copy
import express from "express"; import axios from "axios"; import cors from "cors"; const app = express(); const port = 5000; app.use(cors()); // Define a backend API app.get("/get-instance", async (req, res) => { try { // Get the Wix access token from the `authorization` header const accessToken = req.headers["authorization"]; if (!accessToken) { throw new Error("Access token is required."); } // Extract the app instance ID from the access token const tokenResponse = await axios.post( "https://www.wixapis.com/oauth2/token-info", { token: accessToken, }, ); const instanceId = tokenResponse.data.instanceId; // Create a new access token with an app identity const newTokenResponse = await axios.post( "https://www.wixapis.com/oauth2/token", { grant_type: "client_credentials", client_id: "<YOUR_APP_ID>", client_secret: "<YOUR_APP_SECRET>", instanceId: instanceId, }, ); const elevatedAccessToken = newTokenResponse.data.access_token; // Use the new token to get instance data const instanceResponse = await axios.get( "https://www.wixapis.com/apps/v1/instance", { headers: { Authorization: `Bearer ${elevatedAccessToken}`, }, }, ); return res.json(instanceResponse.data); } catch (error) { console.error("Error processing request:", error.message); return res.status(500).json({ error: "Failed to process request" }); } }); app.listen(port, () => { console.log(`Server running at http://localhost:${port}`); });

Frontend: Call your backend

The following example creates a custom element that makes a request to the get-instance endpoint.

Copy
import { site } from "@wix/site"; import { createClient } from "@wix/sdk"; // Create a Wix Client with site authentication and site host const myWixClient = createClient({ auth: site.auth(), host: site.host({ applicationId: "<YOUR_APP_ID>" }), }); class MyCustomElement extends HTMLElement { constructor() { super(); // Inject the Wix access token to your custom element this.accessTokenListener = myWixClient.auth.getAccessTokenInjector(); } connectedCallback() { this.innerHTML = "<p>My custom element loaded successfully!</p>"; this.callMyBackend(); } async callMyBackend() { try { // Send the access token to your backend const response = await myWixClient.fetchWithAuth( "<YOUR_API_BASE_URL>/get-instance", ); const data = await response.json(); console.log("Response from get-instance:", data); } catch (error) { console.error("Error calling get-instance:", error); } } } customElements.define("<YOUR_CUSTOM_ELEMENT_TAG_NAME>", MyCustomElement);

See also

Did this help?