3D Twin implementation guide

Apps should be implemented as embed elements on your website.
You should not implement app using iframe - it will heavily decrease mobile UX experience.
 
Element that is used to render app must have defined sizes - width and height. It is important for proper app rendering.
Your AppID:
Basic implementation

Basic implementation is to copy HTML code on the right and paste it in target place in website code.
Proper app rendering requires target element to have defined width and size.

Code in HTML section
content_copy
<div id="sm3de"></div> <script src="https://oneappappsprd.z6.web.core.windows.net/launcher/production/app.js" data-appid="[PUT-YOUR-APPID-HERE]"> </script>
Example CSS Styles for propper layout
content_copy
<style> #sm3de { width: 100%; height: calc(100vh - 100px); // adjust to website } </style>
Configure your implementation
link

Configuration below allows to adjust app behaviour to your needs. Select features and they will be added to example code on the right.

Features:

Load app as overlay
loadAsOverlay: boolean
Open app as screen overlay. This feature requires website to control app visibility.
Initial view
initViewId: number
Choose initial view. View ID can be obtained from URL params or by contacting our support team. Usually they are in order: 1, 2, 3, ...
viewId is number representation of all 3d views visible in app it is possible to check viewId from url query: '&sm-viewer-view=2'
App language
initLang: "en" | "pl" | "de" | "fr" | "it" | "he" | "es" | "bg" | "el" | "pt" | "ro" | "nl"
Set apps language
Initial view rotation
initViewRotation: number
Sets the initial rotation frame of the 3D view. Value from 0 to 119.
Init units filters
unitFilterOverride: { default: Record< string, | { min: number | null | undefined; max: number | null | undefined; } | { selected: | number[] | ((options: { values: (string | number)[] }[]) => number[] | undefined) | undefined } | { textSearch: string; } | undefined >; init: Record< string, | { min: number | null | undefined; max: number | null | undefined; } | { selected: | number[] | ((options: { values: (string | number)[] }[]) => number[] | undefined) | undefined } | { textSearch: string; } | undefined >; }
Sets default and init filtering of units in app
// Range config min: number | null | undefined // pass value for min range max: number | null | undefined // pass value for max range /** * null -> force empty value * undefined -> inherit default value from config */ // Select config selected: | number[] | ((options: { values: (string | number)[] }[]) => number[] | undefined) | undefined /** * EXAMPLE * ======= * Status options: [All, Available, Reserved, Sold] * Indexes: * 0 -> All * 1 -> Available * 2 -> Reserved * 3 -> Sold * * To select option "Available" code should be: * selected: [1] * * To select more options "Available, Reserved": * selected: [1, 2] * * To select dynamically generated options with function code should be: * selected: (options) => { * const index = options.findIndex(option => option.values.includes("{option-value-or-id}")) * return index < 0 ? undefined : [index]; * } */

Hooks:

Custom contact form
onContactFormClicked: (units: Unit[]) => void
App allows to user custom contact form when user clicks "send message" button. Provide function that should be executed on button click.
Custom handling of analytical events
onAnalyticEvent: (event: AnalyticEvent) => void
Function is called to handle analytical events
Action after user sent contact form request
onContactFormSent: (contactFormData: JsonObject) => void
Provided function will be called after user submiots contact request. Argument of function will contain user data and selected units.
"Phone" button in app
onPhoneClicked: () => void
Providing function will display "phone" button in app, which will trigger provided function.
Action after overlay app close
onOverlayClose: () => void
Function will be called after closing app that was opened in overlay mode
Additional data in 3D Estate Contact Form
rfpExternalData: () => JsonObject
Function that handles passing additional data to 3D Estate Contact Form. Function will be called when user sends contact form. Proper handling of extra data need configuration in 3D Estate system - please contact our support.
Add custom UTM data to contact form
rfpUtmData: () => UtmData
Function that handles passing additional UTM data to 3D Estate Contact Form. Function will be called when user sends contact form. Proper handling of extra data need configuration in 3D Estate system - please contact our support.
type UtmData = { utm_source?: string; utm_medium?: string; utm_campaign?: string; utm_term?: string; utm_content?: string; fbclid?: string; gclid?: string; [key: string]: string | undefined; }
Handling of custom app actions
onAppAction: (id: string, data: JsonObject) => void
Provided function will be called after a specific event, such as clicking an additional button in the details panel. The function returns the action ID and any additional data that may be passed as part of that action. Proper handling of the custom app action requires configuration in the 3D Estate system - please contact our support
Custom share link
onShareCustomLink: () => string
Provided function should return a custom link that will be used when the share button is clicked.
Custom share handling
onShare: () => void
Provided function will be called when the share button is clicked, allowing custom handling of the share action.

Interaction with app instance

Set app language
setLocale: (locale: string) => void
Call this function to change app language. App may support only selected languages.
Close App
closeApp: () => void
Allows to close app

App configuration:

Options that change the appearance and behaviour of the app. Passed inside the appFeatures object within props.

Hide share button
appFeatures.disableShare: boolean
Hides the share button in the app.
Disable contact form
appFeatures.disableRFP: boolean
Removes the contact form and every enquiry button - in the unit details, the unit list and the compare screen.
Disable unit compare
appFeatures.disableUnitCompare: boolean
Removes the unit compare screen and every "add to compare" button.
Auto-open on mobile when a unit is selected
appFeatures.autoOpenOnMobileIfUnitOpen: boolean
On mobile devices the app opens automatically when a unit is set at start-up (for example via unitId or unitCustomCrmId). With no unit selected the app stays collapsed.
Hide fullscreen button
appFeatures.disableFullscreenButton: boolean
Hides the button that toggles fullscreen mode.
Hide screenshot button
appFeatures.disableScreenshotButton: boolean
Hides the screenshot button from every bottom navigation - the building viewer and all tour players.
Hide outlines toggle
appFeatures.disableOutlinesSwitchButton: boolean
Hides the button that toggles unit outline visibility. The outlines themselves are unaffected.
Disable investment tour
appFeatures.disableInvestmentTour: boolean
Removes every entry point to the investment tour: the button in the building viewer navigation and the tour pins. Unrelated POI pins keep their own configuration.
Simple config
Advanced config
Code in HTML section
content_copy
<div id="sm3de"></div> <script> window.AppLauncher3DEOAConfig = { appId: "[PUT-YOUR-APPID-HERE]", rootElement: "sm3de", }; </script> <script src="https://oneappappsprd.blob.core.windows.net/$web/launcher/production/app.js"></script>
Example CSS Styles for propper layout
content_copy
<style> #sm3de { width: 100%; height: calc(100vh - 100px); // adjust to website } </style>
URL Params
link

It is possible to set default and start values for the filtering module. To do this, add parameters to the URL as shown in the example below.


Set filters
It is possible to set default and start values for the filtering module. To do this, add parameters to the URL as shown in the example below.
https://your-url.com/?sm-filters-rooms-default-min=2&sm-filters-rooms-default-max=3&sm-filters-status=1,2 Range filters - default state &sm-filters-{filterName}-default-min={number} &sm-filters-{filterName}-default-max={number} - init state &sm-filters-{filterName}-init-min={number} &sm-filters-{filterName}-init-max={number} Select filters - default state &sm-filters-{filterName}-default=number,number // provide indexes of options that should be selected - init state &sm-filters-{filterName}-init=number,number // provide indexes of options that should be selected EXAMPLE Status options: [All, Available, Reserved, Sold] Indexes: 0 -> All 1 -> Available 2 -> Reserved 3 -> Sold Selected All: &sm-filters-status-default=0 Selected Available,Reserved: &sm-filters-status-default=1,2