SeatpanoDocs

Integration recipes

Filter a listing on section click

map.on("select", (sel) => showOnly(sel.sections ?? [sel.section])); // areas cover several sections
map.on("deselect", () => showAll());

Highlight the map from a listing card

card.querySelector("button").onclick = () => map.select(card.dataset.section);

Inventory-aware shading

Pass event (with apiBase) and the map fetches that event's sellable sections itself. To shade from your own data instead, fetch availability server-side or client-side and pass or set it:

const { sections } = await fetch(`${apiBase}/v1/venues/${venue}/availability?event=${event}`,
  { headers: { "X-Api-Key": key } }).then((r) => r.json());
map.setAvailability(sections); // null → show everything

Event configuration comes from the event

A Bulls game and a Blackhawks game are different products with different renders, polygons and surfaces. Pass the product for the page's event and the map will not show a dropdown:

Seatpano.load({ …, product: event.venueConfiguration /* "bulls" | "blackhawks" */ });

Omit product only on pages with no event context; the SDK then shows an in-map dropdown as a fallback.

Named areas (clubs, lounges) on team charts

Bands the chart names instead of numbering are clickable areas. select fires with the area id and sections, every space the area stands for: filter by sections. Calling map.select("CLUBA") for a space that has no shape of its own selects its area.

Row bands

Sections keep one shape by default. Pass vantages: "bands" to let a click zoom into a section and reveal its row bands for a second, row-level pick; pass rows: "front" | "central" | "back" to choose which row a plain click shows and to limit the gallery to it. See the SDK reference.

Present the venue's own 3D viewer

Some venues require their own viewer. Their builds declare presentation.views: "iomedia" and the map then opens the venue's IOMEDIA Virtual Venue in an iframe with no gallery of Seatpano's stills. To force either behaviour yourself:

popover: { source3d: "iframe", galleryScope: "none" }      // venue's viewer only
popover: { source3d: "auto", galleryScope: "product" }     // Seatpano's stills + 360°

Dark pages

The map has no background of its own. On a dark page it outlines the chart's ink automatically; set --vm-accent, --vm-fill and --vm-fill-hover to suit your palette.

"View 3D" behaviours

Deep links

Read section from your URL on load and call map.select(section) after the ready event. Write it back inside your select handler.

Iframe fallback (no third-party script on your page)

If your page cannot run our script, embed the map as an iframe from https://embed.seatpano.com and talk to it over postMessage. Your key still applies: the embed page forwards your page's origin to the API, so the licence's domain binding is enforced (your page must not set Referrer-Policy: no-referrer).

Simplest form, with the small host helper (served to licensed keys):

<div id="venue-map"></div>
<script src="https://api.seatpano.com/v1/sdk/embed.js?key=YOUR_KEY"></script>
<script>
  const map = SeatpanoEmbed.mount({ container: "#venue-map", key: "YOUR_KEY",
    venue: "united-center", product: "bulls", event: "EVT1", theme: "flat" });
  map.on("select", ({ section, vantage }) => filterOffers(section, vantage));
  map.on("deselect", () => filterOffers(null));
  // map.select("117"); map.setAvailability([...]); map.openViewer("117"); map.destroy();
</script>

Or with no script at all:

<iframe src="https://embed.seatpano.com/?key=YOUR_KEY&venue=united-center&product=bulls&event=EVT1&theme=flat"
        style="width:100%;height:480px;border:0" title="Seat map" allow="fullscreen"></iframe>
<script>
  window.addEventListener("message", (e) => {
    if (e.origin !== "https://embed.seatpano.com" || e.data?.source !== "seatpano") return;
    if (e.data.type === "select") filterOffers(e.data.payload.section, e.data.payload.vantage);
    if (e.data.type === "resize") frame.style.height = e.data.payload.height + "px";
  });
  // commands: frame.contentWindow.postMessage({ source: "seatpano", type: "select", args: ["117"] }, "https://embed.seatpano.com");
</script>

Messages from the embed: { source: "seatpano", type, payload } where type is ready | select | deselect | hover | view3d | viewerClose | level | product | error | resize. Commands to the embed: { source: "seatpano", type, args } with type in select | clearSelection | setAvailability | setProduct | setLevel | setView | openViewer. URL parameters mirror Seatpano.load options: key, venue, product, event, level, view, theme, accent, vantages, rows, availability (comma list).

Server-side access

Licensed customers can also call the hosted API directly from their own servers, for example to read which sections are sellable for an event or to list licensed venues. That reference is provided with your license key; contact [email protected].

Replacing an existing 3D Digital Venue embed

The event model is intentionally close: DVM.loadModule("map_viewer", …) → Seatpano.load(…); DVM click with nodes[0].id → select with section; enter/leave → hover. Section ids are the same venue section keys.