---
title: "Add a 3D seat view to your website"
description: "Add an interactive 3D venue and 360° view-from-seat to your ticketing website with the SeatLayer Buyer SDK, from install through fallback behaviour."
---

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

# Add a 3D seat view to your website

This tutorial adds a 3D seat view to a ticketing website: buyers orbit the
venue, fly to a seat, and open its 360° view — then select that seat through the
same picker and hold that already drives your 2D checkout. There is no separate
3D model to commission and no second chart to keep in sync; the 3D scene is
built from the chart you already publish.

Test mode is free with no time limit and no card, so you can complete every step
below before a live account exists. For a walkthrough of what buyers see, see
[what buyers see in a 3D seat map](https://seatlayer.io/3d-seat-map/).

## 1. Install the package

```sh
npm install @seatlayer/js@0
pnpm add @seatlayer/js@0
yarn add @seatlayer/js@0
bun add @seatlayer/js@0
```

For script-tag, browser ESM, React, Vue, and Angular routes, see the
[install options for all frameworks](/buyer-sdk/install).

## 2. Enable 3D on the SeatPicker

3D is a progressive enhancement of the picker you already mount. Two options
turn it on: `enable3D` for the interactive venue, and `seatView` for the 360°
view-from-seat actions.

```js title="buyer-picker.js" {4,5,6}
const picker = new SeatPicker({
  container: "#picker",
  event: "ev_9f3a",
  publicKey: "pk_test_…",
  enable3D: true,
  seatView: true,
});

await picker.render();
```

`enable3D` is `true` when WebGL2 is available, and `seatView` is `true` by
default. Set `enable3D: false` when an embed must remain strictly 2D, and
`seatView: false` to hide 360° view-from-seat actions in both 2D and 3D.

> **Public and private audiences**
>
> `publicKey` gives a Platform event one direct, exact-origin, Public-sale-only
> bootstrap; the resulting bearer remains in memory and the first response
> carries both the chart and compact inventory status. Login, presale, partner,
> and channel inventory instead require `buyerAccessTokenProvider` or
> `buyerAccessToken` from your authenticated backend. An explicit scoped
> credential always takes precedence over `publicKey`.

## 3. Drive the view from your own UI

Buyers get a built-in **Map | 3D** switch. Your application can drive the same
state — useful for a “show my seat” button or an order-history screen.

```js title="venue-tour.js"
picker.setBuyerView("venue3d");
console.log(picker.getBuyerView()); // "venue3d"

// Enter 3D and move directly to a known seat.
picker.setBuyerView("venue3d", {
  flyToSeatId: "A-12",
});

picker.setBuyerView("map");
```

Calling `setBuyerView("venue3d", { flyToSeatId })` while already in 3D moves the
existing camera without rebuilding the scene.

> **Use a seat id**
>
> `flyToSeatId` must identify a seat that exists in the loaded chart. Store the
> seat id from the SDK selection; do not derive it from display text in your UI.

## 4. Mirror the view into your own route

`onBuyerViewChange` reports map/3D entry, exit, and targeted-seat changes as
`{ view, seatId? }`. Mirror it into a host route so a copied URL reopens the
same venue at the same seat.

```js title="deep-linked-tour.js"
const picker = new SeatPicker({
  container: "#picker",
  event: "ev_9f3a",
  publicKey: "pk_test_…",
  enable3D: true,
  seatView: true,
  onBuyerViewChange: ({ view, seatId }) => {
    syncHostRoute({ view, seatId });
  },
});
```

The public demo does this with `?tour=3d&seat=<seat-id>`, so browser Back and
Forward restore the map, the 3D overview, and the targeted seat without
rebuilding application state.

## 5. Forward the 3D journey to analytics

`onAnalytics` receives the same 3D events the picker emits, with
`{ surface: "buyer" }` plus event-specific properties.

```js title="3d-analytics.js"
const picker = new SeatPicker({
  container: "#picker",
  event: "ev_9f3a",
  publicKey: "pk_test_…",
  onAnalytics: (event, properties) => {
    analytics.capture(event, properties);
  },
});
```

Current events include `3d_opened`, `3d_orbit_engaged`, `3d_seat_picked`,
`3d_cinematic_played`, `3d_cinematic_skipped`, `3d_cinematic_cancelled`,
`3d_panorama_opened`, and `3d_panorama_closed`. A failing analytics sink does
not break the picker.

## 6. Know the fallback behaviour

3D never becomes a requirement for selection or checkout:

- it is shown only when the browser supports WebGL2;
- it is lazy-loaded only when the buyer enters 3D; and
- it is always paired with the standard 2D map.

`max3DSeats` defaults to `60,000` on desktop and `30,000` on small or low-core
devices, and host overrides are accepted. Keep the built-in toggle
discoverable rather than forcing every buyer into 3D, keep any controls outside
the picker synchronized with `getBuyerView()`, and test low-power devices and
browser WebGL restrictions.

## Before you ship

- [ ] WebGL2 available and unavailable both tested.
- [ ] A seat with an authored image and one using the generated fallback.
- [ ] Live availability changing while 3D is open.
- [ ] Keyboard exit and return to the 2D selection.
- [ ] Mobile portrait and reduced container heights.
- [ ] Host theming with sufficient text and control contrast.

## Questions

### How do I add a 3D seat preview to my ticketing website?

Install `@seatlayer/js`, mount `SeatPicker` on an event, and set `enable3D: true`
with `seatView: true`. The picker renders the 2D map, the interactive 3D venue,
and the 360° view-from-seat from the same published chart, so the seat a buyer
picks while orbiting the venue is the seat that enters the hold and your
checkout handoff.

### Does the 3D view need a separate chart?

No. The 3D scene is built from the chart you already publish, and venue
landmarks authored in the Designer are shared with the 3D scene rather than
maintained as a separate model. The 3D scene receives the same availability and
selection changes as the 2D picker, so seat state stays consistent while the
buyer changes view.

### Where do the 360° images come from?

SeatLayer resolves the closest available source: a seat or row-level authored
image, then a floor-level fallback, then a venue-wide fallback, then a
geometry-generated preview. Buyer UI distinguishes an authored image from a
generated preview. See the
[3D buyer view reference](/buyer-sdk/3d-view) for the progressive-panorama
metadata and the private-media transport rules.

### Can I do this in React?

Yes — the same options apply to the React wrapper. Start from the
[React seating chart tutorial](/buyer-sdk/react-seating-chart) and add
`enable3D` and `seatView` to the `SeatPicker` component it builds.

For the complete purchase flow, continue to the
[checkout example](/examples/complete-checkout).

Source: https://docs.seatlayer.io/buyer-sdk/add-3d-seat-view/index.mdx
