How it works
floors.js runs completely outside Nuxt and Vue. It loads as a standalone script that patches the browser's history APIs — pushState, replaceState, and the popstate event — to detect route changes in your app.
Under the hood, Nuxt uses Vue Router for all navigation. When a visitor moves from /pricing to /docs/getting-started, Vue Router calls pushState, and floors.js picks that up automatically. No Nuxt plugin, no Vue composable, no re-renders.
Because it works at the browser level, it's compatible with Nuxt 3, Nuxt 2, file-based routing, dynamic routes, and middleware — all out of the box.
Installation
There are two ways to add floors.js to a Nuxt app. Both work identically.
export default defineNuxtConfig({
app: {
head: {
script: [
{ src: 'https://floorsjs.com/embed.js', 'data-key': 'flr_...' }
]
}
}
})
<script setup>
useHead({
script: [{ src: 'https://floorsjs.com/embed.js', 'data-key': 'flr_...' }]
})
</script>
Replace flr_... with your site key from the floors.js dashboard. The script loads asynchronously and won't block your app's rendering or hydration.
Works with Nuxt routing
Nuxt's file-based routing maps directly to floors.js rooms. Every route in your pages/ directory becomes a room that visitors can inhabit together.
- Static routes —
pages/about.vue→ visitors on/aboutare in the same room - Dynamic routes —
pages/blog/[slug].vue→ each blog post is its own room - Nested routes —
pages/dashboard/settings.vue→/dashboard/settingsis a separate room - Catch-all routes —
pages/[...slug].vue→ each resolved path gets its own room
No configuration needed. Middleware, layouts, and route guards don't affect floors.js — it only cares about the final URL in the browser.
Configuration
All configuration is done via attributes on the script tag (or the equivalent object in nuxt.config). No JavaScript API needed.
- data-key (required) — your site key, used to group visitors across your domain
- data-server (optional) — custom WebSocket server URL if you're self-hosting
- data-name (optional) — pre-set the visitor's display name instead of generating a random one
FAQ
head property in nuxt.config.js using script: [{ src: 'https://floorsjs.com/embed.js', 'data-key': 'flr_...' }]. Works the same way.useHead call in a process.client check or use a v-if condition to only inject the script for certain users or environments.