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

# PixelSetupElement

> Installs the Whop Pixel and wires conversion events: copy the snippet, check a page for it, confirm the events fire. Mount it inline, or inside your own overlay.

<Info>**Upcoming** — generated from the latest merged element source; documents unreleased development. Use the channel picker at the top of the sidebar for the docs of a published release.</Info>

*In development — not yet part of a stable release.*

Belongs to the [`Websites`](/elements/upcoming/websites/overview) group. Render `<PixelSetupElement />` inside it (React), or call `websites.create('pixel-setup', { … })` on the handle (vanilla) — consumer props and `on<Event>` callbacks both go in the create options / JSX props.

<Note>This element can be mounted **inline** (`create`) or opened as a **modal** overlay (`createOverlay`).</Note>

## Preview

A live, interactive demo of this element with sample data:

<div data-whop-demo-shell style={{ position: "relative", minHeight: "320px", transition: "min-height 200ms ease" }}>
  <div data-whop-demo-skeleton style={{ position: "absolute", inset: "0", borderRadius: "12px", background: "rgba(140, 140, 140, 0.12)", pointerEvents: "none", transition: "opacity 200ms ease" }} />

  <div data-whop-demo-native="element:websites/pixel-setup" data-whop-elements-version="" style={{ position: "relative" }} />
</div>

## Usage

<div data-whop-usage="websites/pixel-setup">
  <CodeGroup>
    ```tsx React theme={null}
    import { WhopElements, Websites, PixelSetupElement } from "@whop/elements-react";
    import { loadWhop } from "@whop/elements";

    function Example() {
      return (
        <WhopElements elements={loadWhop()}>
          <Websites /* options */>
            <PixelSetupElement onRedirectUrlChanged={(payload) => console.log("redirectUrlChanged", payload)} onScanned={(payload) => console.log("scanned", payload)} onFinished={(payload) => console.log("finished", payload)} onEventVerified={(payload) => console.log("eventVerified", payload)} />
          </Websites>
        </WhopElements>
      );
    }
    ```

    ```html Vanilla theme={null}
    <script src="https://js.whop.cloud/elements/amber/elements.js" data-whop-elements></script>
    <script type="module">
      const websites = window.WhopElements().websites.create({ /* options */ });
      websites.create('pixel-setup', {
        onRedirectUrlChanged: (payload) => console.log("redirectUrlChanged", payload),
        onScanned: (payload) => console.log("scanned", payload),
        onFinished: (payload) => console.log("finished", payload),
        onEventVerified: (payload) => console.log("eventVerified", payload)
      }).mount('#websites-pixel-setup');
    </script>
    ```
  </CodeGroup>
</div>

## Props

<ResponseField name="accountId" type="string">
  The company (`biz_…`) whose pixel this is. Required — the snippet, scans and invites all run against it. Defaults to `""`.
</ResponseField>

<ResponseField name="accessToken" type="string">
  A scoped token for the scans and the developer invite. Mint it on your server with `POST /v1/access_tokens` and set a fresh one before it expires. Omitted, the calls carry the viewer’s own session, which only answers same-origin.
</ResponseField>

<ResponseField name="destinationUrl" type="string">
  The page to check, scanned on mount. Leave it blank and the wizard asks for one. Read once at boot, so `update()` will not retarget mid-flow — mint a fresh mount for a different page. Defaults to `""`.
</ResponseField>

<ResponseField name="eventName" type="string">
  Optional. An event that must fire on that page (`lead`, `schedule`, `view_content`, …); the events step blocks until it is detected. Unset, every event is offered and none is required. Events Whop records server-side (`purchase`, `subscribe`, trials, checkout steps) are ignored. Read once at boot. Defaults to `""`.
</ResponseField>

<ResponseField name="redirectUrl" type="string">
  A URL the destination redirects to, when the event fires there instead. The merchant can also set one in the wizard — listen for `redirectUrlChanged` and pass it back next time. Defaults to `""`.
</ResponseField>

<ResponseField name="initialStep" type="&#x22;events&#x22; | &#x22;install&#x22;">
  Where the wizard opens: the install step, or straight onto `events` when the pixel is already there and only the conversion event is missing. Defaults to `"install"`.
</ResponseField>

<ResponseField name="showIntro" type="boolean">
  Open on the "why a pixel" splash. Turn it off where the merchant already knows why they are here — a campaign flow that sends them in mid-launch — and the wizard opens straight on the install step. Defaults to `true`.
</ResponseField>

<ResponseField name="showInviteDeveloper" type="boolean">
  Offer the "Invite a developer to install it" path. Hide it where the people using your embed should not be inviting members onto the Whop team behind it. Defaults to `true`.
</ResponseField>

## Events

Pass a callback in the create options (or React prop) to receive these.

### `onRedirectUrlChanged`

The merchant set or cleared a redirect URL in the wizard. Persist it and pass it back as `redirectUrl` next time.

**Signature:** `((payload: { url: string; }) => void)`

### `onScanned`

A pixel scan settled. Fires for every URL the wizard checks, so your own install badge can follow it. `primary` marks the page being set up: the funnel checker scans whatever else the merchant lists, other hostnames included, so gate on it before you treat a result as being about their site.

**Signature:** `((payload: { url: string; status: "installed" | "missing" | "unreachable"; installed: boolean; primary: boolean; }) => void)`

### `onFinished`

Done was pressed. Re-check the page yourself — this says the wizard finished, not that your requirements are met.

**Signature:** `((payload: Record<string, never>) => void)`

### `onEventVerified`

The merchant walked their funnel with "Verify live" and this event fired — proof it is wired where a server-side scan cannot reach.

**Signature:** `((payload: { url: string; event: string; }) => void)`

### `onLoaderStart`

Fired the moment the element's own loading skeleton has painted inside its frame — the earliest point a consumer-managed loading state can hand off without ever exposing a blank. Always precedes `onReady`; most consumers only need `onReady`.

**Signature:** `(() => void)`

### `onReady`

Fired once the element has booted and painted its first complete frame.

**Signature:** `(() => void)`

### `onError`

Fired when the element fails to load or crashes; the element shows its own error fallback. `message` is human-readable; framework refusals also carry `code` (e.g. `HOST_SOURCE_FAILED`, with `sourceKey` naming the failed hostState key) so hosts can switch on codes, never message text.

**Signature:** `((e: { message: string; code?: string | undefined; sourceKey?: string | undefined; }) => void)`

## Methods

Call these on the element handle — the return of `create` (vanilla) or the component `ref` (React).

### `mount`

Place the element on the page: appends its container to `target` (a CSS selector or an element) and starts loading. Nothing renders until this is called. React consumers never call it — the component mounts itself.

**Signature:** `(target: string | HTMLElement) => void`

### `destroy`

Remove the element from the page and release its frame and subscriptions. Safe to call more than once. React consumers never call it — unmounting the component does it.

**Signature:** `() => void`

### `update`

Change this element's consumer props after mount — it re-renders with the merged props. React consumers never call it — updating the JSX props does the same.

**Signature:** `(options: Partial<PixelSetupElementProps>) => void`

## Styling

Each part below is a stable class name — safe to depend on. Restyle a part by mapping its class to a **style declaration object** under `appearance.classes` (properties camelCase or kebab-case, values as strings with units — the same shape as React's `style` prop). The element renders in its own frame, so page stylesheets can't reach it: these declarations are sanitized against a safe-property allowlist and injected inside the frame for you.

| Class                     | Targets                                          |
| ------------------------- | ------------------------------------------------ |
| `.whop-PixelSetupSurface` | The pixel setup wizard root — one step at a time |

```ts theme={null}
const websites = whop.websites.create({
  appearance: {
    classes: {
      'whop-PixelSetupSurface': { borderRadius: '8px', fontWeight: '600' }
    }
  }
});

// restyle live at any point — the same shape through update()
websites.update({
  appearance: {
    classes: { 'whop-PixelSetupSurface': { fontWeight: '700' } }
  }
});
```

In React, pass the same object as the `appearance` prop on `<Websites>`; `appearance` also applies globally at `WhopElements({ appearance })`.
