> ## Documentation Index
> Fetch the complete documentation index at: https://docs.omneo.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Profile Portal theme extension

> Embed the Omneo Profile Portal in any Shopify theme and control it via window functions.

The **Profile Portal theme extension** embeds the Omneo Profile Portal inside any Shopify theme as an iframe dialog. The extension handles authentication for the logged-in customer using the [Omneo CX app proxy](/extensions/shopify/authentication), so no token plumbing is required in theme code.

<Info>
  This extension ships with the Omneo CX Shopify app. See the [Shopify extension overview](/extensions/shopify/overview) for installation.
</Info>

## Enable the extension on a theme

The Profile Portal is a [Shopify global theme app extension](https://shopify.dev/docs/apps/build/online-store/theme-app-extensions). To enable it on a theme:

<Steps>
  <Step title="Open the theme editor">
    In Shopify admin, go to **Online Store → Themes**, then **Customize** the theme you want to enable Profile Portal on.
  </Step>

  <Step title="Enable the app embed">
    Open the **App embeds** panel (the puzzle-piece icon), find **Profile Portal**, and toggle it on.
  </Step>

  <Step title="Configure the block">
    Set the block settings to match your storefront (see [Block settings](#block-settings)).
  </Step>

  <Step title="Save the theme">
    Save the theme. The portal dialog is now available on every page of that theme.
  </Step>
</Steps>

### Block settings

| Setting             | Description                                                                                                                                                         |
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Button Selector** | CSS selector for the element that opens the portal when clicked. Defaults to `#profile-portal-button` (the selector used by the Profile Portal Button block).       |
| **Path**            | Default path to load inside the portal iframe (for example, `/profile`). Leave blank to open the portal root.                                                       |
| **Base URL**        | Override the portal base URL. Leave blank to use `https://{tenant}.profileaction.io`.                                                                               |
| **Enable Overlay**  | When enabled, the portal opens over a darkened overlay and closes when the overlay is clicked. When disabled, the portal closes on any click outside its container. |

## Profile Portal Button block

The **Profile Portal Button** is an optional section block that renders a pre-styled account icon with the `#profile-portal-button` ID. Drop it into a header or any section to get a no-code way to toggle the portal.

| Setting      | Description                                                                                         |
| ------------ | --------------------------------------------------------------------------------------------------- |
| **Icon URL** | URL to an external SVG that replaces the default account icon. Leave blank to use the bundled icon. |

If you already have an account button in your theme, skip this block and point the Profile Portal **Button Selector** setting at your existing element instead.

## Authentication

The Profile Portal fetches a token from `GET /apps/cx` via the Omneo CX Shopify app proxy. Shopify automatically authenticates the request against the storefront session, so the token is scoped to the currently logged-in customer (or is anonymous when no customer is logged in).

Tokens are cached in `sessionStorage` under the key `omneo-cx-{customerId}-id-token` and refreshed automatically when they expire or when the logged-in customer changes. You do not need to manage tokens manually unless you are integrating with a custom login flow, in which case the [window functions](#window-functions) below give you full control.

See [Shopify Authentication](/extensions/shopify/authentication) for the underlying token exchange.

## Window functions

The Profile Portal block exposes the following functions on `window` for programmatic control from theme code, custom buttons, or third-party scripts.

### `openOmneoCXProfilePortal(path, force)`

Opens the profile portal dialog.

| Parameter | Type      | Description                                                                                                                                                                                        |
| --------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `path`    | `string`  | Path to load inside the portal iframe (for example, `/profile/rewards`). Omit to use the block's default **Path** setting.                                                                         |
| `force`   | `boolean` | When `true`, opens the requested `path` directly even if the current session is anonymous. When `false` (default), anonymous sessions are redirected to `/login` regardless of the requested path. |

```javascript theme={null}
// Open the portal at the default path
window.openOmneoCXProfilePortal()

// Open the portal at a specific path
window.openOmneoCXProfilePortal('/rewards')
```

### `closeOmneoCXProfilePortal()`

Closes the profile portal dialog and resets the iframe `src` to `about:blank` so no session is kept alive in the background.

```javascript theme={null}
window.closeOmneoCXProfilePortal()
```

### `fetchOmneoCXToken(force)`

Fetches an ID Proxy token from `/apps/cx`, updates internal state, and caches the result in `sessionStorage`.

| Parameter | Type      | Description                                                                                                                                                                      |
| --------- | --------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `force`   | `boolean` | When `true`, bypasses the cache and refresh checks and fetches a brand new token. When `false` (default), reuses the cached token if it is still valid for the current customer. |

Returns a promise that resolves to `{ token, tenant, isAnon }`.

```javascript theme={null}
const { token, tenant, isAnon } = await window.fetchOmneoCXToken()
```

### `loginOmneoProfilePortal()`

Forces a fresh token fetch (bypassing the cache) to pick up the currently logged-in Shopify customer. Use this immediately after a customer logs in if the portal needs to reflect the new session without a full page reload. Emits the `omneo-cx-profile-portal-login` event on success.

```javascript theme={null}
window.loginOmneoProfilePortal()
```

### `logoutOmneoProfilePortal()`

Logs the current customer out of the portal:

* Clears the cached token from `sessionStorage`.
* Resets internal state to anonymous.
* Closes the dialog if it is open.
* Emits the `omneo-cx-profile-portal-logout` event.

Call this when the Shopify customer logs out so the portal does not retain a stale token.

```javascript theme={null}
window.logoutOmneoProfilePortal()
```

### `resetOmneoProfilePortal()`

Fully resets the portal to its initial state:

* Removes every `omneo-cx*` key from `sessionStorage`.
* Resets all internal state (token, tenant, anonymous flag, open state, current iframe path).
* Clears the iframe `src`.
* Emits the `omneo-cx-profile-portal-reset` event.

Use this to recover from a stuck state or to forcibly clear all portal data on the client.

```javascript theme={null}
window.resetOmneoProfilePortal()
```

## Events

In addition to the window functions, the portal emits custom DOM events on both `document` and the portal container. Subscribe to these for analytics or to react to portal lifecycle changes.

| Event                                 | Fired when                                                                 | `detail` payload                                  |
| ------------------------------------- | -------------------------------------------------------------------------- | ------------------------------------------------- |
| `omneo-cx-profile-portal-initialized` | The portal finishes initial setup and the first iframe load is dispatched. | `{ timestamp, customerId, path, isAnon, tenant }` |
| `omneo-cx-profile-portal-opened`      | `openOmneoCXProfilePortal` is called.                                      | `{ timestamp, customerId, path }`                 |
| `omneo-cx-profile-portal-closed`      | `closeOmneoCXProfilePortal` is called.                                     | `{ timestamp, customerId }`                       |
| `omneo-cx-profile-portal-path-loaded` | The iframe finishes loading a new path.                                    | `{ timestamp, customerId, path, isAnon }`         |
| `omneo-cx-profile-portal-login`       | `loginOmneoProfilePortal` succeeds.                                        | `{ timestamp, customerId, action: 'login' }`      |
| `omneo-cx-profile-portal-logout`      | `logoutOmneoProfilePortal` is called.                                      | `{ timestamp, customerId, action: 'logout' }`     |
| `omneo-cx-profile-portal-reset`       | `resetOmneoProfilePortal` is called.                                       | `{ timestamp, customerId, action: 'reset' }`      |

```javascript theme={null}
document.addEventListener('omneo-cx-profile-portal-opened', (event) => {
  console.log('Portal opened at', event.detail.path)
})
```
