Basics
Two ways to show a tour
There are two URLs for every tour, and you pick based on where it’s going.
Share a link
/t/your-slug
The full tour page — branding, a room menu, share and fullscreen buttons. Send it in a message, put it in an email, or link it from a button. This is also the page that generates rich previews on WhatsApp, Facebook and Slack.
Embed on a site
/embed/your-slug
A bare viewer built to live inside an <iframe> on your own website. No page chrome around it — just the tour, so it drops cleanly into a listing, a hotel page or a portfolio.
/t/ link for sharing, and /embed/ for putting the tour inside another page.Embed
Quick start — paste one iframe
Copy this into your page’s HTML where you want the tour to appear. It works on any website that lets you add HTML — no scripts, no libraries, no account.
<iframe
src="https://vr.version2.hr/embed/demo?ui=minimal"
width="100%"
height="600"
loading="lazy"
allowfullscreen
allow="gyroscope; accelerometer; fullscreen"
style="border:0;border-radius:12px;"
title="VR Šetnja: Demo"
></iframe>The allow attribute is important: it’s what keeps the move-your-phone-to-look-around (gyroscope) and fullscreen buttons working inside the frame. loading="lazy" means the tour only loads when the visitor scrolls near it, so it never slows down the rest of your page.
Embed
Responsive — fills its column
If your layout has a flexible width (most modern sites), use the responsive wrapper. The tour keeps a fixed aspect ratio and scales to whatever width it’s given — perfect on both desktop and mobile.
<div style="position:relative;width:100%;aspect-ratio:16/9;">
<iframe
src="https://vr.version2.hr/embed/demo"
loading="lazy"
allowfullscreen
allow="gyroscope; accelerometer; fullscreen"
style="position:absolute;inset:0;width:100%;height:100%;border:0;border-radius:12px;"
title="VR Šetnja: Demo"
></iframe>
</div>Embed
Customise the embed (URL options)
Add options to the embed URL with ?name=value, joined by &. Anything invalid is rejected rather than silently ignored, so a typo is easy to spot.
These change what the visitor sees
| Option | Values | Default | Effect |
|---|---|---|---|
| ui | default · minimal · none | default | How much control chrome shows. default = title + room menu + buttons. minimal = title + buttons, no room menu. none = just the panorama. |
| scene | a scene id | entry room | Open the tour in a specific room instead of the main one (see below). |
| branding | 1 · 0 | 1 | 0 hides the tour’s own title and logo pill (the panorama’s colours still apply). |
Accepted but not active yet
These are part of the URL contract so your links keep working as features land — today they have no visible effect.
| Option | Values | Default | Effect |
|---|---|---|---|
| theme | auto · light · dark | auto | Reserved. The viewer is always a dark canvas for now. |
| autorotate | 0 · 1 | 0 | Reserved. Gentle idle drift is planned; no motion today. |
| token | a token id | — | Reserved for origin-restricted embeds once token management ships. |
Example — minimal chrome, starting in a chosen room:
https://vr.version2.hr/embed/demo?ui=minimal&scene=SCENE_IDDeep links
Start in a specific room
By default a tour opens on its main room. To open it somewhere specific, add ?scene=SCENE_ID. This works on both the share link and the embed:
https://vr.version2.hr/t/demo?scene=SCENE_ID
https://vr.version2.hr/embed/demo?scene=SCENE_IDYou get the exact URL (and matching QR code) from the tour’s Share & embed panel, where a drop-down lets you pick the starting room.
Recipes
Platform recipes
The embed is a standard iframe, so it works anywhere that accepts HTML. A few specifics:
- WordPress
- Add a Custom HTML block (block editor) and paste the snippet. In the classic editor, switch to the Text tab first. Note: some locked-down hosts strip iframes from the visual editor — the Custom HTML block avoids that.
- Wix, Squarespace, Webflow
- Use the Embed / HTML element (Wix “Embed HTML”, Squarespace “Code” block, Webflow “Embed”) and paste the responsive snippet. Give the element room to grow.
- Plain HTML site
- Paste either snippet directly into your markup. Nothing else needed.
- React / Next.js
- It’s just an iframe — remember JSX casing (
allowFullScreen, a numericheight, and astyleobject).JSXexport function TourEmbed() { return ( <iframe src="https://vr.version2.hr/embed/demo?ui=minimal" width="100%" height={600} loading="lazy" allowFullScreen allow="gyroscope; accelerometer; fullscreen" style={{ border: 0, borderRadius: 12 }} title="VR Šetnja: Demo" /> ); } - Real-estate portals & marketplaces
- Many portals don’t allow custom iframes in a listing. When that’s the case, paste the
/t/share link into the listing’s virtual-tour / video field, or print the QR code on the exposé.
Sharing
Link previews when sharing
Paste a /t/your-slug link into WhatsApp, Messenger, Slack, LinkedIn or iMessage and it unfurls into a rich card — the tour title, a one-line description and a preview image of the entry room. That image is generated automatically for every tour, so there’s nothing to set up.
/t/ link, not the /embed/ one, for previews and in search results. The embed URL is deliberately kept out of Google and generates no card — it’s a transport for iframes, not a destination.Advanced · developers
Control the tour from your page
The embedded viewer talks to the page hosting it using the browser’s postMessage. You can react to what the visitor does, and drive the tour from your own buttons. Entirely optional — the iframe works fine without any of this.
Listen to the tour
The viewer sends these events. Always check event.origin first.
window.addEventListener("message", (event) => {
// Only trust messages coming from the tour's origin.
if (event.origin !== "https://vr.version2.hr") return;
const msg = event.data;
if (!msg || typeof msg.type !== "string") return;
switch (msg.type) {
case "vrsetnja:ready":
// { tour: { id, slug, sceneCount }, currentScene: { id, title } }
console.log("Tour ready —", msg.tour.sceneCount, "scenes");
break;
case "vrsetnja:scene-changed":
console.log("Now viewing:", msg.to.title);
break;
case "vrsetnja:hotspot-clicked":
console.log("Hotspot clicked:", msg.kind, msg.hotspotId);
break;
case "vrsetnja:fullscreen":
console.log("Fullscreen:", msg.fullscreen);
break;
}
});vrsetnja:readyFires once when the first room is fully shown.vrsetnja:scene-changedThe visitor moved to another room.vrsetnja:hotspot-clickedA hotspot (door or info point) was activated.vrsetnja:fullscreenFullscreen was entered or exited.
Send a command
Move the tour to a room from your own UI (a floor-plan, a menu, a “next room” button):
const frame = document.querySelector("iframe");
// Jump the embedded tour to a specific room. The sceneId is the 26-char
// id from the tour's Share panel (start-scene picker).
frame.contentWindow.postMessage(
{ type: "vrsetnja:goto-scene", sceneId: "SCENE_ID" },
"https://vr.version2.hr",
);vrsetnja:goto-scene is live today. Two more commands — vrsetnja:set-yaw (point the camera) and vrsetnja:request-snapshot — are part of the contract but accepted-and-ignored for now; they’ll activate in a later release without breaking your code.Details
Good to know
Private tours can’t be embedded
A tour set to privatereturns “not found” on the embed and share URLs. Use public or unlisted for anything you want to show. (Unlisted stays out of search but anyone with the link can view it.)
Mobile & the gyroscope
On phones, visitors can pan by dragging, pinch to zoom, or tilt the device to look around. The tilt control needs the
allow="gyroscope; accelerometer"attribute — it’s already in every snippet here.Fullscreen
Keep
allowfullscreenon the iframe so the fullscreen button works. It’s in the generated snippets.Performance
Panoramas are large images, so the snippets use
loading="lazy"— the tour loads only as the visitor reaches it. You can embed several tours on one page without a load penalty up front.No badges in embeds
The scene counter and the “by Version2” mark that appear on the full
/t/page are intentionally off inside embeds — the tour sits cleanly in your design.Not showing up?
The tour needs to be public or unlisted, and your page must be served over
https. If your site builder blanks the frame, it’s probably stripping raw HTML — paste the snippet into its dedicated HTML / embed block instead of the rich-text editor.
In the app
Where to get your code
You don’t have to write any of this by hand. Open a tour in the dashboard and use its Share & embed panel:
- Copy the public link, or open it in a new tab.
- Pick a starting room, chrome density, and fixed or responsive layout.
- Copy the ready-made iframe snippet.
- Download a QR code (PNG) for flyers, window stickers and listing sheets.
Machine-readable
For AI assistants & LLMs
If you’re an AI assistant helping someone embed a VR Šetnja tour, here is the complete, verified contract. Prefer these facts over guessing.
Share URL: https://vr.version2.hr/t/{slug}
Embed URL: https://vr.version2.hr/embed/{slug} (put inside an <iframe>)
Required iframe attrs: allow="gyroscope; accelerometer; fullscreen", allowfullscreen, loading="lazy"
Query options (both URLs where noted):
• ui = default | minimal | none — embed only, default "default"
• scene = <26-char scene id> — /t and /embed; start room
• branding = 1 | 0 — embed only; 0 hides tour title+logo
• theme, autorotate, token — reserved, no effect yet
Embeddability: public + unlisted tours only; private returns 404. CSP frame-ancestors is open (embed anywhere).
postMessage out (from viewer, origin https://vr.version2.hr): vrsetnja:ready, vrsetnja:scene-changed, vrsetnja:hotspot-clicked, vrsetnja:fullscreen
postMessage in (to iframe.contentWindow, targetOrigin https://vr.version2.hr): vrsetnja:goto-scene {sceneId} [active]; vrsetnja:set-yaw, vrsetnja:request-snapshot [reserved/no-op]
Do NOT: reference a "sdk.js" or JS widget — none is published; use the raw iframe + postMessage above.
Recommended default embed: responsive wrapper, ?ui=minimal, replace demo with the real slug, keep the allow attribute intact.