Map integration
Embed the interactive floor plan on your website by importing load from https://unpkg.com/@expofp/floorplan and pointing it at your event’s manifest URL (see also load() in the API reference).
💡 Make sure the container has a set width and height
Method 1: Initialize with JavaScript
- Add a container element to hold the floor plan.
- Load the SDK from CDN in a
<script type="module">block, for exampleimport { load } from 'https://unpkg.com/@expofp/floorplan'. - Call
loadwith a manifest reference ($refto your event’smanifest.json) and options (for exampleelement).
This method gives you direct control over initialization in your application’s JavaScript.
📝 Other options are available — see the API reference.
Add a container with id="floorplan" (or pass another element in options), then use a module script:
import { load } from 'https://unpkg.com/@expofp/floorplan';
load(
{ $ref: 'https://demo.expofp.com/manifest.json' },
{ element: document.querySelector('#floorplan') },
);Single-page apps (React, Vue, Svelte…)
When the plan lives on a route that mounts and unmounts, call destroy() on the way out. It unmounts the UI, releases the listeners, analytics and map resources, and empties the container so the same element can host a later load(). It is also safe to call while the plan is still loading — that cancels the load rather than throwing.
One element can host only one plan at a time — a load() that starts before the previous plan finished tearing down fails with Element already in use. destroy() is synchronous, but the plan you call it on only exists once load() has resolved, so an unmount that fires mid-load has nothing to tear down yet. Chaining both through one promise keeps them in order. This matters in development, where React's StrictMode mounts every effect twice:
// Module scope, not a ref: it serialises load → destroy → load across every
// mount of the route, including two that overlap on a fast navigation.
let chain = Promise.resolve();
function Map() {
useEffect(() => {
const element = document.getElementById('floorplan');
let plan;
chain = chain
.then(async () => {
plan = await load({ $ref: MANIFEST }, { element });
})
// Every stage ends in a catch: one rejected load would otherwise leave
// `chain` permanently rejected, and no later mount or teardown on it
// would ever run.
.catch((error) => console.error('floor plan failed to load', error));
return () => {
chain = chain
.then(() => plan?.destroy())
.catch((error) => console.error('floor plan failed to tear down', error));
};
}, []);
return <div id="floorplan" style={{ height: 600, width: '100%' }} />;
}If you also await ready, catch it as well: destroying a plan mid-load rejects that promise, because the initialization it was waiting on has been cancelled.
Method 2: Using an iframe
To embed the floor plan, insert an iframe with your event URL.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Iframe Integration — ExpoFP SDK Example</title>
</head>
<body
style="margin: 0; height: 100vh; display: flex; align-items: center; justify-content: center"
>
<iframe
style="width: 90%; height: 90%; border: 0"
src="https://demo.expofp.com?consent=denied"
allow="clipboard-read; clipboard-write"
></iframe>
</body>
</html>