Delight VR Changelog

1.4.11 (2018-07-18) [latest]

  • Fixed a rare case where user was redirect to cors-fallback-url when an error in the system occurred
  • Fixed a rare misclassification where some phones got classified as a tablet and thus were unable to enter VR mode
  • Fixed HLS crossorigin use-credentials handling to correctly handle cases where crossorigin=”use-credentials” flag is being used for HLS videos
  • Fixed an issue where the body background color was not reset correctly after entering and leaving VR again

1.4.10 (2018-07-10)

  • Add updateDimensions() to element API to trigger embed size recalculation. This is useful when visibility of the element changes and the player should update the dimensions according to the new DOM state
  • Add tag filtering support to <dl8-hub>
  • Allow disabling of player autostart when being redirected to the cors fallback url with the “cors-fallback-no-autostart” attribute
  • Fix hud button positioning when certain elements like controls or title are force hidden
  • Fix autostart-vr bug when autostarting WebVR or autostarting fullscreen mode is not possible due to user gesture constraints
  • Add “dl8-customization-force-native-vr-resolution” meta tag to force 1:1 resolution of the device instead of the default optimized resolution for Android devices
  • Reduce hover scaling of <dl8-tour> elements
  • Fix pause and play indicators erroneously appearing in non-video elements

1.4.8 (2018-06-06)

  • play 2D videos without following cors fallback url
  • disable redirection to cors-fallback-url on iOS >= 11.1
  • save video quality selection across sites
  • fix duplication of qualities in quality dropdown
  • fix issue caused by very large preview thumbnail sprite sheets
  • add ‘autostart’ attribute to automatically start a content element (including a ‘tap-to-unmute’ hint to support common video autoplay behavior)
  • add ‘disable-tap-to-unmute’ option to disable the automatic muting of videos when autostart attribute is present
  • add ‘autostart-vr’ attribute to launch directly into VR mode
  • add option to disable capturing of scroll events (‘disable-scroll-capture’)
  • add option to disable capturing of touch events (‘disable-touch-capture’)
  • add option to disable capturing of mouse events (‘disable-mouse-capture’)
  • add option to disable vertical dragging on mobile (‘disable-vertical-touch-dragging’)
  • add option to disable vertical dragging on desktop (‘disable-vertical-mouse-dragging’)
  • add option to disable the 3D HUD for controlling videos in VR (‘disable-3d-hud’)
  • add meta tag to skip the VR wizard (<meta name=”dl8-customization-skip-vr-wizard”>)
  • add ‘autoplay’ attribute to <dl8-recommendation> sub-element to support automatically playing the first recommendation when the video has ended
  • add ‘hidden’ attribute to <dl8-recommendation> sub-element to hide the recommendation UI
  • add <dl8-tour-content-portal> sub-element which behaves like the <dl8-tour-portal> but can activate another content instead of jumping to another tour image

1.4.7 (2018-05-14)

  • Add Oculus Go controller support
  • Improve DASH playback

1.4.6 (2018-05-02)

  • Fix magic window mode for Chrome Android > 60 with enabled WebVR API
  • Fix regression where  recommendations where sometimes not removed correctly when hopping between recommendations
  • Fix HLS quality selection of sources bigger than 1080p on IE11
  • Fix dynamic DOM deletion of dl8 elements

1.4.5 (2018-04-06)

  • Fix HLS and DASH quality selection
  • Fix rare issue with adaptive streaming playback when switching between different Delight VR contents
  • Improve video frame update interval to fix irregular video frames in certain situations

1.4.0 (2018-03-16)

  • Add numerous freely configurable banner ad spots
  • Add ability to switch qualities for adaptive video streams (HLS / DASH)
  • Add ‘drag-controls-damping’ parameter to common API to control the damping speed of the drag controls
  • Add more customization options to tour portals
  • Add tour info hotspots
  • Add Hear360 8Ball audio format support
  • Add new phone from late 2017 and early 2018 to the VR wizard
  • Add new VR headsets to the VR wizard
  • Enable spatial audio for Firefox Mac and Firefox Android
  • Improve visibility of center HUD elements on mobile
  • Fix device motion calculation for Chrome >= 66 and Firefox >= 54
  • Fix native WebVR path in Chrome for Android
  • Prevent fallback to native 2D video when there is a content error
  • Prevent showing VR hud on mounted device events when VR is not active

1.3.11 (2017-11-29)

  • Use referrer url for redirection to mobile site via QR code when on a cors fallback URL
  • Fix redirect to iframe on mobile when enabled via meta tag

1.3.10 (2017-11-08)

  • Add iPhone X to phone library
  • Add currentTime and duration getter to <dl8-video> element

1.3.9 (2017-10-30)

  • Fix start-lat and start-lon for <dl8-img>
  • Fix iOS 9 video playback issue
  • Fix iOS 10/11 wakelock problem for looping videos
  • Add .seek() API for <dl8-video>
  • Add loading events to get insights into resource loading flow
  • Add new customization options for fine grain visibility control of on-screen UI

1.3.8 (2017-10-12)

  • Fix cubemap slice unpacking for non square cubemap sides.
  • Add iPhone 8 and iPhone 8 Plus to VR Wizard

1.3.7 (2017-09-20)

  • Use canvas fallback on iOS 11 for HLS to circumvent playback bug introduced in iOS 11 and higher
  • Fix macOS Safari 11 video priming
  • Fix initial 3D UI state in Oculus Internet on GearVR
  • Add custom “x-dl8-evt-ready” DOM event to wait for before using Delight VR element specific APIs
  • Add ability to add “window-name” and “window-features” attribute to dl8-external-content to provide more control over link opening behavior

1.3.5 (2017-09-14)

  • Removed custom font to increase compatibility and reduce file size
  • Better callback attribute support for hub in dynamic mode and recommendations
  • Increased recommendation maximum count
  • Improved 3D UI layouting

1.3.4 (2017-08-10)

  • Fix iOS >=10.3 in-VR canvas text rendering

1.3.3 (2017-08-09)

  • Fix console error with third-party iframe messaging
  • Add browser page visibility handling to smartly pause and resume video

1.3.2 (2017-08-03)

  • Rename ‘Enter VR’ to ‘Start’ for confirming starting the player inside VR browsers like the Oculus Browser and the Samsung Internet Browser
  • Improve recommendation horizontal scroll reset on video pause
  • Fix issue with recommendations that were not properly deleted after exiting the player
  • Fix bug where it was not possible to add live video or external content to the hub
  • Fix video y-flipping issue on Windows 10 IE

1.3.0 (2017-07-21)

  • Add recommendations feature for showing related videos and external links directly inside the player
  • Improve settings view interaction
  • Improve video source management logic
  • Fix Hub state saving

1.2.16 (2017-07-18)

  • Add all Sony Xperia XZ variants and Xiaomi Redmi 3 to phone list
  • Improve dialog and overlay styling
  • Fix iOS 11 video rendering issue
  • Fix seeking bar time overlay positioning
  • Fix resetting viewport meta tags after closing player
  • Fix seeking bar width on Chrome with device pixel ratio > 1

1.2.12 (2017-06-23)

  • Fix rendering bug with antialiasing enabled on Android Chrome 58 on a subset of phones
  • Improve OnePlus 3 phone detection

1.2.10 (2017-06-16)

  • Add specialized <dl8-live-video> UI in VR
  • Add preview thumbnail support through VTT files
  • Add Gear VR and Daydream controller support
  • Improve general UX in Oculus Browser
  • Improve resolution for the Oculus Browser and Samsung Internet on Gear VR
  • Improve visibility of the VR video control UI
  • Made drag controls the default on tablets
  • Fix IFrame handling when it is embedded via relative URL
  • Fix native cardboard and daydream VR support for Chrome 59 and upward

1.2.9 (2017-05-19)

  • Add option to flag video sources as incompatible for Samsung VR
  • Fix sideloading via Samsung VR

1.2.8 (2017-05-16)

  • Add <dl8-live-video> element that supports live streaming UI
  • Add popular recent phones to the wizard phone select list
  • Fix autoplay for cors-fallback-url redirects
  • Fix hub state resurrection on returning from a content
  • Improved performance for iOS HLS video playback
  • Workaround for Oculus Browser bug where video sphere was not drawn to screenbuffer

1.1.23 (2017-05-05)

  • Prefer progressive video source in favour of HLS on iOS browsers to improve playback performance
  • Fix CORS check to incorporate different ports
  • Improve HLS ABR Manager algorithm to improve video quality

1.1.20 (2017-04-27)

  • Add iFrame support
  • Add improved adaptive bitrate manager for HLS that tracks current FPS, MAX_TEXTURE_SIZE and more
  • Improve async webworker HLS parsing
  • Fix native cardboard VR support in Chrome
  • Fix HLS fallback video support
  • Fix rare bug when autostarting player via cors-fallback-url

1.1.11 (2017-04-13)

  • Fix problem with gyroscope on iOS 10.3 and higher

1.1.9 (2017-03-07)

  • Fix scrolling bug when exiting out of inline mode
  • Fix Android 7 resizing
  • Fix misc. style collisions
  • Fix rare shader
  • Improve Get VR dialog on no-WebGL
  • Add support for native 2D fallback on low-end and flat video
  • Add support for seeking preview

1.1.8 (2017-02-24)

  • Fix VR autostart post QR-Scan on Chrome

1.1.7 (2017-02-16)

  • Fix CB Enabler Link
  • Fix Gaze Interaction when Gamepad connected on HTC Vive
  • Fix multiple <script> embed

1.1.6 (2017-02-10)

  • Fix Daydream WebVR compatibility
  • Fix Chrome 57 WebComponent initialization order

1.1.5 (2017-01-27)

  • Fix spatial audio sometimes not initializing correctly
  • Fix spatial audio on Firefox Mobile and Firefox OSX as well as Safari OSX
  • Improve spatial audio fallback and error handling for unsupported platforms (iOS Safari / IE 11)

1.1.3 (2017-01-20)

  • Fix channel order for ambiX on Safari

1.1.2 (2017-01-20)

  • Fix iOS viewport rendersize bug
  • Improve quality switching behavior

1.1.1 (2017-01-11)

  • Fix quality switching for flat video

1.1.0 (2017-01-10)

  • Add DASH and HLS support
  • Add support for ambisonics spatial audio
  • Add orientation compass
  • Add compact wizard
  • Add Daydream support
  • Add Pixel phones
  • Add video event support
  • Add support for “fps” and “format” attributes per source
  • Add support for cors-fallback handling on all elements
  • Add support for preferred camera controls attribute
  • Fix scroll position bug in IE11
  • Fix iPhone 6/7 Plus fullscreen bug
  • Fix Gear VR Samsung Internet exit bug
  • Improve native hardware HMD controller fallback to gaze
  • Improve font rendering

1.0.6 (2016-11-17)

  • Fix rare iPad video rendering error on iOS 10
  • Fix iPhone (6/6s/7)Plus VR distortion detection
  • Fix IE11 exit fullscreen button functionality
  • Improve Samsung Galaxy S(6/6 Edge/7/7 Edge) VR distortion detection
  • Add revamped settings panel selection menu for qualities and camera controls

1.0.5 (2016-11-11)

  • Improve rendering performance on mobile devices
  • Improve react update frequency on video playback
  • Improve legibility of 3D UI fonts

1.0.4 (2016-11-07)

  • Fix autoplay on cors fallback url redirect on iOS devices
  • Improve code fetch behavior on iOS devices
  • Improve error feedback on shader compile, parse and fetch errors
  • Update link to free cardboard enabler app

1.0.3 (2016-10-28)

  • Fix guarding undefined gamepad object on certain devices
  • Fix CORS redirect on IE11
  • Fix ES6 issue with IE11
  • Fix exit tracking event
  • Fix issue with double slash cors fallback url

1.0.0 (2016-10-12)

  • Fix x-dl8-evt-exit CustomEvent
  • Fix scroll to top on exit player issue
  • Fix error report url encoding issue
  • Fix WebVR in Firefox Nightly
  • Fix iOS10 video texture upload
  • Fix Android wakelock for VR
  • Improve aspect ratio handling of embed container on resize
  • Improve dynamic DOM manipulation of dl8 elements
  • Add WebVR 1.1 support


1.0.0-beta5-rc12 (2016-09-12)

  • Fix iOS (<=9) replay action on video end
  • Fix cardboard photo loading on very large photos
  • Fix missing cardboard enabler app link in VR Wizard
  • Improve video quality pre-checking
  • Improve iOS 10 video playback performance
  • Add iPhone 7 and iPhone 7 Plus to phone list
  • Add Galaxy Note 7 to phone list
  • Add Alcatel Idol 4 and Idol 4S to phone list
  • Add Samsung Gear VR SM-R322 (2015er version) HMD distortion
  • Add Innovator Edition Samsung Gear VR SM-R320 to HMD selection
  • Add media event listeners API on dl8-video (spec)

1.0.0-beta5-rc11 (2016-08-25)

  • Fix discarding of qualities when video sources are not supported
  • Fix display issue of watermark in IE11
  • Add “force-inline” display-mode to force displaying player inline on every device

1.0.0-beta5-rc10 (2016-08-08)

  • Fix pause video on error
  • Fix tablets can’t launch VR mode
  • Improve preload progress indicator handling
  • Improve unification to one error report json
  • Improve exiting player on cors fallback url goes back to original url

1.0.0-beta5-rc9 (2016-08-07)

  • Fix HUD watermark
  • Fix spacebar being captured on other input fields on the site
  • Improve style guard for img hover

1.0.0-beta5-rc8 (2016-08-02)

  • Improve quality list update by only triggering when old and new content is a video

1.0.0-beta5-rc7 (2016-08-02)

  • Fix 3D UI quality dropdown when qualities are unplayable

1.0.0-beta5-rc6 (2016-08-01)

  • Improve performance by using react’s PureComponent for pure views
  • Improve using native preload attribute for video prefetching control

1.0.0-beta5-rc5 (2016-08-01)

  • Fix missing IE CORS handling
  • Fix content badge hiding for non white-label users
  • Fix escape key for exiting player
  • Improve creation of native video element late in the process to prevent downloading unnecessary content
  • Add auto-redirect for cors-fallback-url
  • Add preload attribute to dl8-video to control preloading behavior

1.0.0-beta5-rc4 (2016-07-23)

  • Fix brand customization behavior to cover cases where not all customizations are made
  • Add option to hide brand logo, watermark and content type badge
  • Add Samsung Galaxy S7 Edge to supported phones

1.0.0-beta5-rc3 (2016-07-19)

  • Fix enabling smooth border for cinema or flat video in VR only
  • Fix cut off hover texts in tour

1.0.0-beta5-rc2 (2016-07-15)

  • Fix hover border style in embed
  • Fix smooth border when going into cinema mode
  • Improve guard video quality when no video is active

1.0.0-beta5-rc1 (2016-07-14)

  • Fix styling of title bar in combination with certain watermark image aspects
  • Fix possible erroneous style overrides from external stylesheets
  • Fix Samsung Internet on Gear VR button handling
  • Fix rare issue when switching tabs with a connected gamepad
  • Fix iOS video audio handling when multiple qualities are present
  • Improve core-js es6 polyfill handling
  • Improve crossorigin attribute sanitizing
  • Improve differentiation between no webgl errors and regular errors
  • Improve error reporting
  • Improve on-screen replay, pause and play indicator animations (moved to css based rendering)
  • Improve CORS handling on MacOS Safari and IE
  • Add dl8-cinema element for displaying flat video in a customizable virtual cinema
  • Add inline tag attribute checking and warning screen
  • Add automatic removal of video qualities when source is not supported (either because of CORS, encoding or other issues)
  • Add fullscreen button on mobile devices when fullscreen mode is supported and flat video is playing and look around is disabled

1.0.0-beta4 (2016-06-30)

  • Fix precision of differentiation between click and drag
  • Fix replay button visibility in some cases
  • Fix flashing of replay, play and pause indicator
  • Fix title styling
  • Fix autoplay of videos on mobile
  • Improve iOS video buffering
  • Improve loading progress visualization
  • Improve iOS audio syncing
  • Improve VR video experience by pausing when entering VR and seeking to the beginning to not miss a beat
  • Add flat video support for monoscopic and stereoscopic 3D videos (see docs for more info)
  • Add start and exit as external Javascript APIs for all elements
  • Add play and pause as external Javascript APIs for video element
  • Add custom watermark support to VR video UI

1.0.0-beta3 (2016-06-17)

  • Fix dl8 embed container handling. In inline mode the player now stays in DOM layouting flow
  • Fix Firefox Android button styling issues
  • Fix Internet Explorer mute/unmute button
  • Add initial VR 3D video player interface
  • Add gaze interaction on tour portals
  • Add hover info title on tour portals
  • Add seek head time display
  • Add start-lat and start-lon to every element to set up user starting orientation
  • Changed default secondary color to a more subtle dark grey

1.0.0-beta2 (2016-06-13)

  • Fix focus of VR button to prevent toggling VR on spacebar
  • Fix double script import
  • Fix wheel speed for IE11
  • Fix CSS to prevent overrides
  • Fix video undersampling
  • Fix iPhone 5 selection in Wizard
  • Fix Firefox/Android VR mode resize problem
  • Add Cardboard Photo formats for dl8-img and dl8-tour
  • Add content error overlay
  • Add support for room scale VR
  • Add better CORS handling for iOS/Safari
  • Add CORS fallback handling
  • Add support for audio on iOS
  • Add QR code for non-vr browsers
  • Add Gamepad support
  • Add video quality switching
  • Add better highp float handling
  • Add float precision friendly distortion mesh uv
  • Add white-label support
  • Add IE11 video rendering fallback
  • Add more HMDs to list of supported headsets (i.e. MR.CARDBOARD)
  • Remove exit dialog
  • Remove h1 tags to improve SEO for customers

1.0.0-beta1 (2016-05-09)

Initial Beta Release



Supported HMDs

We strive to support as many HMDs as possible with Delight VR. To make things accessible to the end-user we provide users with a wizard, enabling to configure the user’s HMD. Here is a list of all currently supported devices by Delight VR.

Cardboard compatible headsets

Through our Wizard and our predefined distortion database we support nearly any common Cardboard compatible headset on the market (i.e. Google Cardboard v1.0, Google Cardboard v2.0, Zeiss VR One and many more) on Android Phones as well as on iPhone.

Google Daydream

Is fully supported including Daydream controllers with Chrome Android 59 and up.

Samsung Gear VR

Is fully supported in the Oculus Internet Browser (Internet Tab in Oculus Home) including full Gear VR Controller support.

Alternatively Samsung Internet from the Oculus Store can be used. Users will be prompted to enable WebVR automatically.

Finally any regular mobile browser can be used with the Samsung Gear VR in Cardboard mode with the Cardboard Enabler app.

Desktop VR headsets

All major desktop VR headsets are supported. Specifically Oculus Rift (CV1 and DK2) and HTC Vive with WebVR enabled browser (as of writing these are special WebVR builds of Chromium and Firefox nightly).

Supported platforms

All major browsers and platforms are supported by Delight VR, in more detail:

  • Recent versions of Chrome on Windows, OSX, Linux, Android, and iOS.
  • Recent versions of Safari on OSX and iOS.
  • Recent versions of Firefox on Windows, OSX, and Linux.
  • Recent versions of IE 11 and Edge on Windows.


To ensure that the Delight VR experience is smooth for all users, here are some hints to consider when embedding Delight VR into your HTML.

  • CSS styling: Due to it not being an iframe solution per-se CSS collisions can happen in rare instances, especially if global element styles are applied.
  • Whitelabel logo CORS requirement: When using a brand logo and/or brand watermark logo, be sure to supply correct CORS headers on your remote server when serving the logos from a cross-origin domain to ensure the logos are displayed correctly in the VR controls. For maximum compatibility we recommend to host logos on the same domain or use a data-uri.

Dynamic Affiliate Spots

Dynamic Affiliate Spots (Beta)

Delight VR Dynamic Affiliate Spots provide a standard non-intrusive way to display affiliate items on top of Delight VR Video content. They do not strive to be completely customizable, but rather be constrained in order to provide a user-friendly, standardized yet highly convertible affiliate space. They integrate neatly with the UX of Delight VR and thus seem naturally embedded into the playout experience.


To enable the feature a <dl8-affiliate> tag must be placed as a child of <dl8-video>. The <dl8-affiliate> tag itself supports two children: <dl8-affiliate-spot> and <dl8-affiliate-item>.


Affiliate spots describe the appearance and behavior of places where you want your items to display in Delight VR. Affiliate spots can be defined by using the <dl8-affiliate-spot> tag. The tag currently supports two attributes:


placing=”<string>” [mandatory]

The location/placing of the spot. This attribute can currently be one of:

Will be shown when the user enters the VR Wizard screen. This placing supports multiple items.

Will be shown when the user pauses the Video.

Will be shown when the user presses the VR button, but does not have a Headset connected (on desktop). This placing supports multiple items.


cta=”<string>” [optional]

Defines a CTA (Call To Action) text to be displayed at a sensible location on the defined spot.


Affiliate items are what ultimately gets displayed and is what you want to show/sell. Affiliate items are described by the <dl8-affiliate-item> tag. Once you have defined a number of affiliate items, they are distributed randomly across the <dl8-affiliate-spot>s as defined above. An affiliate item needs at least an “url” and a “name” attribute to be valid. But it supports more attributes to describe the affiliate item further and to customize it’s appearance.


url=”<URL>” [mandatory]

The URL to redirect to when the affiliate item is clicked.


name=”<string>” [mandatory]

The name that should be displayed on the affiliate item.


thumbnail=”<URI>” [optional]

An URI pointing to a thumbnail Image describing the product. It is recommended to use square aspects but you can also use slightly wide images. Also it is recommended to use medium resolution images to avoid oversampling and high load-times.


description=”<string>” [optional]

An optional more detailed description of the item you want to redirect to.


A full example of a <dl8-video> with a <dl8-affiliate> configuration could look as follows:

<dl8-video title="Example-Video" author="Jane Doe" format="STEREO_180_LR" poster="example.jpg" display-mode="inline">
  <source src="example.mp4" type="video/mp4" />
  <source src="example.webm" type="video/webm" /> 
  	<dl8-affiliate-spot placing="WIZARD" cta="Need a headset?"></dl8-affiliate-spot>
  	<dl8-affiliate-spot placing="PAUSE"></dl8-affiliate-spot>
  	<dl8-affiliate-spot placing="NO_VR_SCREEN" cta="Get the full experience!"></dl8-affiliate-spot>
    	name="Item 1"
     	description="Get Item 1 Here!"
     	name="Item 2"
    	description="Get Item 2 Here!"
     	name="Item 3"
    	description="Get Item 3 Here!"

Banner Advertisements

Banner Advertisements (Beta)

The Delight VR Advertisement feature allows you to inject display banner ads into advertisement spots within the player’s HTML UI as well as the VR 3D UI of the player. This allows you to display your banners directly within VR. For the first iteration of the feature we support only a select number of spots to not overflow the VR space and player real-estate. The system was kept as extensible as possible and allows you to write a custom JavaScript binding between your ad-network and the player.

Supported Spots

In the HTML portion of the player, only the pause spot is supported at 300x250px. In VR we support four banner placements, alongside the 3D UI (Player Controls). These banners always show when the controls are opened in VR; not only if the video is paused. Keep in mind that if you are using the Delight VR Recommendations feature, the VR_HUD_BOTTOM_BANNER_468X60 spot will be ignored.






To implement the feature on your deployment of Delight VR you have to write the declarative markup and a binding function in JavaScript that will get called each time an advertisement spot is possible to be displayed in the player.


Add the <dl8-advertisement> tag as a child of a <dl8-video> tag.

It requires the attribute on-request-advertisement to be present, which takes a function identifier as a value (see Javascript section for more information about the function implementation).

	<dl8-advertisement on-request-advertisement="requestAdvertisement">


You can define a custom function which acts as a binding layer between the player and your ad provider. This function is called every time the player can display a certain advertisement spot. Information about the spot is passed in the requirement object, passed as a first parameter. Hints are provided in a second object, for contextualized information that could be used to make better decisions on the ad type that is ultimately requested and finally a callback is passed that needs to be called with the final data of what to display. Note that if you don’t want a certain spot to be filled you should call the callback function with null. Below you will find the details needed to implement each part:


function requestAdvertisement(requirement, hints, callback) {
   switch ( {
         const advertisement = // Fetch your advertisement from ad network
         // or callback(null) when no ad should be displayed
         return callback({
            type: //advertisement type
            payload: {
               uri: //advertisement source uri
               adLink: // advertisement url link (only for type image)
      ... // Other cases implementation

requirement (object)

An object that provides information about what spot should be filled, please refer to it to provide a well defined callback object

Requirement object sample:

   type: ['image']

spot (String)

Spot identifier which can be used, for example, in a switch statement to fetch a different asset for this specific spot

type (Array)

Array of available types for the advertisement asset. Values can be image and/or iframe

hints (Object)

An object that provides hints about the state of the player. Useful for data manipulation upon certain conditions, before firing the callback function

hints = {
   screen: {
      width: Integer (px) // Player width,
      height: Integer (px) // Player height,
      fullscreen: Boolean,
      portrait: Boolean,
      vrActive: Boolean
   device: {
      mobile: Boolean,
      tablet: Boolean,
      android: Boolean,
      ios: Boolean,
      ie: Boolean,
      vr: Boolean

callback (Function)

A function that must be called with an object as the first parameter that adheres to the following structure:

   type: String,
   payload: {
      uri: String,
      adLink: String			

type (String)

Accepted values are “image” or “iframe”. In the case of VR spots the value “iframe” is not supported.

payload (Object)

  • URI (String) The URI that is either the image URL or the iframe URL to be displayed as an advertisement.
  • adLink (String) In case the type of the advertisement is “image” this is the target URI that should be navigated to if the user clicks on the advertisement banner.


Video and content recommendations

Delight VR can display related content in 2D as well as VR. This allows for a very convenient user experience as users can jump from one content to another without leaving the experience. You can either add contents statically via HTML markup or dynamically through a Javascript hook. As of now related content can either be a <dl8-video>, <dl8-cinema>, <dl8-live-video> or an <dl8-external-content> element that opens a new URL and can optionally autostart Delight VR on this URL. This enables further use cases like placing ad banners inside the related content widget or redirection of users to other sites with Delight VR content.

The feature can be included by adding the <dl8-recommendation> element inside the <dl8-video>, <dl8-cinema> or <dl8-live-video> element. The <dl8-recommendation> has the following parameters:

title="<string>" [optional]

Specifies the text that is shown above the recommendations in VR to give the related items that are displayed a bit more context. For example if you host a video portal and want to display videos that are related to the current video you could write title=“Related videos” to make it clear for the users that the next clips are videos and related. The default value is “Recommendations”

mode=”<static|dynamic>” [optional]

This indicates the mode on how recommendations are going to be fetched. There is a “static” and a “dynamic” mode. The default is “dynamic”.
In “static” mode simply add <dl8-video> or <dl8-external-content> elements as children to the <dl8-recommendation> element like so:

 <dl8-video ...> 
    <source .../>
    <dl8-recommendation mode="static">
          title="Related Video 1" 
            <source …/>
          title="Related Content 2"

In “dynamic” mode new recommendations are dynamically queried via a Javascript hook that is user defined. This enables you to implement your own recommendation logic based on the current content. To implement dynamic recommendations just add the following parameter:

on-request-recommendation=”<function(requestId, count, recommendationCallback)>”

This function will be called whenever the player needs to be fetched from the server. Through the given arguments you can formulate queries to your own server that then can respond with a set of recommendations. On server response you can create an array of contents (either dl8-video or dl8-external-content) that adhere to the Delight VR json spec and pass them as an argument to the recommendationCallback function. A complete example could look like this:

    // The requestRecommendations function could be named anything and could reside anywhere. 
    // The DVR.requestRecommendations is just an example.
    window.DVR = {
        requestRecommendations: function(id, count, recommendationCallback) {
            // pseudo code
            requestDataFromServer(id, count).then(res => {
                var recommendations = createDelightVRJsonSpecFromResponse(res)

 <dl8-video ...> 
    <source .../>
      on-request-content="DVR.requestRecommendations(id, count, recommendationCallback)"

autoplay & hidden [optional]

You can set the autoplay and hidden attribute to create a recommendation playlist. When the autoplay attribute is provided, the player automatically starts the first recommendation after the video has ended. If you enable hidden, the recommendation interface is hidden from the user. It is best used in conjunction with autoplay to create a hidden playlist.

 <dl8-video ...> 
    <source .../>
    <dl8-recommendation mode="static" autoplay hidden>
          title="Related Video 1" 
            <source …/>
          title="Related Content 2"



With this element you can link to other external URLs. It can only be added to other dl8 elements and can’t be used standalone. As of now it can be added inside a <dl8-recommendation> element and inside a <dl8-hub-content> element. Since it features a poster image and an optional title a common use case is to use this element for placing ads, affiliates, special content or use it as general traffic redirection to other sites with Delight VR content.

   title="External Link 1"

The element features the following attributes:

url="<uri>" [mandatory]

Specifies the URL of the external content. If the URL references a site with Delight VR the autostart attribute becomes important.

title="<string>" [optional]

The title text that will be displayed as a label on the content tile.

poster="<uri>" [optional]

The poster image that will be displayed on the content tile. Please note that a cover layout is used for the poster.

autostart [optional]

If set and the <URI> in the url attribute points to a Delight VR enabled website the Delight VR player on the target page will automatically start. The default is false

window-name="<string>" [optional]

A DOMString specifying the name of the browsing context (window, <iframe> or tab) into which to load the specified external content; if the name doesn’t indicate an existing context, a new window is created and is given the name specified by window-name. This name can then be used as the target of links and forms by specifying it as the targetattribute of <a> or <form> elements. The name should not contain whitespace. Keep in mind that this will not be used as the window’s displayed title.

window-features="<string>" [optional]

A DOMString containing a comma-separated list of window features given with their corresponding values in the form “name=value”. These features include options such as the window’s default size and position, whether or not to include scroll bars, and so forth. There must be no whitespace in the string. See Window features in the MDN for documentation of each of the features that can be specified.



With the <dl8-img> element you can display panoramic images in lots of different formats in VR as well as on desktop and mobile. The <dl8-img> element works much like any normal img tag. You mainly need to specify the src attribute and a format and you’re ready to go.

 <dl8-img src="image.png" poster="poster.jpg" title="Example Image 1"
          author="John Doe" format="STEREO_360_TB">

 <dl8-img src-left="lefteye.jpg" src-right="righteye.jpg" poster="poster.jpg"
          title="Example Image 2" author="Jane Doe" format="STEREO_CUBEMAP">

{src|src-left|src-right}="<uri>" [mandatory]

The image src URI to use. You can optionally provide src-left and src-right to separately define the image for each eye in VR.

format="<string>" [mandatory]

Defines the mono or stereo format the image is provided in. Delight VR supports all common stereo/mono 360/180 equirectangular and spherical formats.

  • STEREO_180_LR: A 180 degree stereo equirectangular mapping, left and right eye being side by side.
  • STEREO_180_LR_SPHERICAL: A 180 degree stereo spherical mapping, left and right eye being side by side.
  • STEREO_180_TB: A 180 degree stereo equirectangular mapping, left and right eye being on top and bottom respectively.
  • STEREO_180_TB_SPHERICAL: A 180 degree stereo spherical mapping, left and right eye being on top and bottom respectively.
  • STEREO_360_TB: A 360 degree stereo equirectangular mapping, left and right eye being on top and bottom respectively.
  • STEREO_360_LR: A 360 degree stereo equirectangular mapping, left and right eye being side by side.
  • MONO_360: A 360 degree mono equirectangular mapping.
  • STEREO_CUBEMAP: A 360 degree stereo cubemap. 6 sides horizontally for each eye. Please provide src-left and src-right for this format. This format is commonly exported from OctaneVR renderer.
  • CARDBOARD_PHOTO: A photo taken with the Cardboard Camera App. This is typically a 360° equirectangular jpg with the left eye as the base image data and the right eye encoded in metadata.



With the <dl8-tour> element you can effortlessly integrate an interactive tour consisting of multiple viewpoints and connected via so called portals in your website. The <dl8-tour> element is the root element and therefore the entry point for defining an interactive tour. It makes use of child elements to describe the actual tour images (or probes) as well as the portals that connect probes with each other. Thus it works much like any other nested DOM structure. The <dl8-tour> element follows the common Delight VR API. See below for an example and all tour specific attributes and child elements.

 <dl8-tour poster="poster.jpg" title="Example Tour 1" author="John Doe"

    <dl8-tour-img probe-id="bathroom" title="Bathroom" format="STEREO_360_TB"
      <dl8-tour-portal to="living-room" lat="0" lon="270" distance="1.5"
                  title="Enter Living Room"></dl8-tour-portal>

    <dl8-tour-img probe-id="living-room" title="Living Room"
                  format="STEREO_360_TB" src="bathroom.jpg">
      <dl8-tour-portal to="bathroom" lat="0" lon="90" distance="1"
                  title="Go to Bathroom"></dl8-tour-portal>


start-probe-id="<string>" [optional]

Defines the id of the <dl8-tour-img> element that should be the starting point of the tour. This id must match one probe-id of a <dl8-tour-img> child element. If nothing is set the first <dl8-tour-img> will be the start of the tour.


The <dl8-tour-img> describes one of the probes the tour is comprised of. It has the following attributes that can be set:

probe-id="<string>" [mandatory]

A unique freely definable id within the scope of the <dl8-tour> that is used throughout the scope of the <dl8-tour> parent element to reference to this probe.

format="<string>" [mandatory]

The image format that should be used for this specific probe. Please note that you can mix and match multiple format types for each of the defined <dl8-tour-img> elements that are part of the <dl8-tour> parent element. See the image element format API for further information.

title="<string>" [optional]

The title string of the probe. This will be used as the player headline when viewing this probe and will further be used as the pop-over text on a portal, when hovered, and when the portal’s “title” attribute is not set.

src="<uri>" [mandatory]

The image src URI to use. You can optionally provide src-left and src-right to separately define the image for each eye in VR.

rotation-y="<number>" [optional]

The angle in degrees of rotation of the probe around the y-axis (up-axis). This attribute can be used in case the probes comprising the tour were not completely aligned and the initial relative rotations of probes have to be adjusted. The default is 0 degrees.


The <dl8-tour-portal> element describes a portal or “hotspot” that connects the parent <dl8-tour-img> with another <dl8-tour-img> and thus forms a portal between those two. It can be placed in a polar coordinate fashion using latitude/longitude and distance. It supports the following attributes:

to="<string>" [mandatory]

Defines the “probe-id” of any <dl8-tour-img> within the scope of the parent <dl8-tour> element to which the portal should lead to. Please note that self referencing probe ids are not possible and will be ignored.

title="<string>" [optional]

The title string of the portal. This will be used in the pop-over text on a portal when it is hovered. Example usages could be “Enter Bathroom” or “Go to Outside”.

lat="<number>" [optional]

The latitude angle in degrees where the portal should be placed.

lon="<number>" [optional]

The longitude angle in degrees where the portal should be placed.

distance="<number>" [optional]

The distance in meters from the viewer to where the portal should be placed. The default is 1 meter.



The <dl8-cinema> element lets users sit in a virtual cinema and watch regular 2D videos as well as 3D stereoscopic videos. The element works much like a normal video tag. You can define different sources with qualities as child elements to tell the element what video content to play on the cinema screen.

Whats special about the dl8-cinema element is that you can freely customize the room the user should sit in and where the virtual screen should be placed.

 <dl8-cinema title="Example Video" poster="poster.jpg" author="John Doe"
             room-format="STEREO_360_TB" room-src="cinema.png"
             format="MONO_FLAT" force-show-cinema>
    <source src="example.mp4" type="video/mp4" />
    <source src="example.webm" type="video/webm" />

format="<string>" [mandatory]

Defines the mono or stereo format the flat video playing on the screen is provided in. Delight VR supports all common 2D flat video and stereoscopic 3D flat video formats.

  • MONO_FLAT: A monoscopic 2D flat video.
  • STEREO_FLAT_LR: A stereoscopic 3D flat video, left and right eye being side by side. The pixel aspect ratio follows the video aspect ratio.
  • STEREO_FLAT_LR_SQUARE: A stereoscopic 3D flat video, left and right eye being side by side. The pixel aspect ratio is square (1:1).
  • STEREO_FLAT_TB: A stereoscopic 3D flat video, left and right eye being on top and bottom respectively. The pixel aspect ratio follows the video aspect ratio.
  • STEREO_FLAT_TB_SQUARE: A stereoscopic 3D flat video, left and right eye being on top and bottom respectively. The pixel aspect ratio is square (1:1).

{room-src|room-src-left|room-src-right}="<uri>" [mandatory]

The room image src URI to use as the cinema. A stereoscopic image works best as it better establishes the room the user sits in. You can optionally provide room-src-left and room-src-right to separately define the image for each eye in VR.
Note that the virtual screen is always displayed in the front (negative z-axis).

room-format="<string>" [mandatory]

Defines the mono or stereo format the room image is provided in. Delight VR supports all common stereo/mono 360/180 equirectangular and spherical formats.

  • STEREO_180_LR: A 180 degree stereo equirectangular mapping, left and right eye being side by side.
  • STEREO_180_LR_SPHERICAL: A 180 degree stereo spherical mapping, left and right eye being side by side.
  • STEREO_180_TB: A 180 degree stereo equirectangular mapping, left and right eye being on top and bottom respectively.
  • STEREO_180_TB_SPHERICAL: A 180 degree stereo spherical mapping, left and right eye being on top and bottom respectively.
  • STEREO_360_TB: A 360 degree stereo equirectangular mapping, left and right eye being on top and bottom respectively.
  • STEREO_360_LR: A 360 degree stereo equirectangular mapping, left and right eye being side by side.
  • MONO_360: A 360 degree mono equirectangular mapping.
  • STEREO_CUBEMAP: A 360 degree stereo cubemap. 6 sides horizontally for each eye. Please provide src-left and src-right for this format. This format is commonly exported from OctaneVR renderer.
  • CARDBOARD_PHOTO: A photo taken with the Cardboard Camera App. This is typically a 360° equirectangular jpg with the left eye as the base image data and the right eye encoded in metadata.

screen-width="<number>" [optional]

Width of the cinema screen in meters. The default is 2.5 meters. Not that depending on the aspect of the video the actual width can be less than the given width.

screen-height="<number>" [optional]

Height of the cinema screen in meters. The default is 1.5 meters. Not that depending on the aspect of the video the actual height can be less than the given height.

screen-distance="<number>" [optional]

Distance from the viewer to the cinema screen in meters. The default is 2 meters.

screen-x-offset="<number>" [optional]

Relative horizontal translation of the screen. With this parameter you can fine tune the placement of the cinema screen in the room. The default is 0.

screen-y-offset="<number>" [optional]

Relative vertical translation of the screen. With this parameter you can fine tune the placement of the cinema screen in the room. The default is 0.

Other <dl8-video> attributes

The dl8-cinema element supports all additional <dl8-video> attributes like loop, muted, crossorigin and fps. You can see the dl8-video API for detailed information.



The Hub is a fully customizable and data-driven Delight VR element that connects multiple VR contents through a navigation hub that is explorable in VR.


The interface presented in the hub is composed of widgets like content grids and menus. These widgets (like the content itself) are created through markup as child elements of the <dl8-hub>. A powerful action system based on filter and sorter actions ensures a flexible approach to what is shown in content views and in which order.

Getting started

The simplest reasonable form of the <dl8-hub> includes a few contents wrapped in a <dl8-hub-content> element and just one grid widget (<dl8-hub-grid>). All widgets and views (i.e. things that are actual interface elements) need to be grouped into a layout component to tell the system how to arrange the widgets around the user. In the current version this layout element is the <dl8-hub-vizor>.

With this basic building blocks at hand a good markup starting point for a simple hub would look like this:

    <dl8-video title="Video 1" poster="p1.jpg" format="STEREO_360_TB">
      <source src="video1.mp4" type="video/mp4"/>
    <!-- ... -->   
    <dl8-img title="Image 6" poster="p2.jpg" src="img.jpg" format="MONO_360">

The result might look something like this:

Hub Markup in Depth

In this section we will go over the different elements that make up the hub in detail and explain their markup and element API.


This is the root element. Since it’s also an embed element like other Delight VR contents (videos, images, etc.) it has the same common API (width, height, poster, title, etc.). There are two additional parameters to control the room that surrounds the hub which behave exactly like the equally named parameters of the <dl8-cinema> element and setup the 360° image for the room:

room-src=”<URI>” (optional)

room-format=”<string>” (optional)

There are several child elements that can be added to the <dl8-hub>. There are two different kinds: Elements that provide data and semantic (<dl8-hub-content>, <dl8-hub-filter>, <dl8-hub-sorter> and elements that provide the visual representation (<dl8-hub-vizor>)


This element groups up all the content that the hub should display. It is important to note that there is a separation of appearance and data at play here. Contents defined as child elements of this grouping element have no visual representation but only provide the data for the visual elements (aka widgets). The child elements can either be regular Delight VR contents (dl8-video, dl8-img, dl8-tour, etc.) or <dl8-hub-group> elements. Additionally you can add <dl8-external-content> elements which represent links to other sites and external content. This allows you to setup things like banner ads, affiliate links and other traffic redirection mechanisms. 

To account for use cases with massive amounts of data and server-side filtering and pagination logic the <dl8-hub-content> mode attribute can be set to dynamic. This in combination with two additional events on the element allow for dynamic fetching of contents for the widgets. The attributes are as follows:


on-request-content=”<function(startIdx, endIdx, filters, sorter, contentCallback)>”
This function will be called whenever the hub detects that a content is missing upon user interaction and needs to be fetched from the server. Through the given arguments you can formulate paginate queries to the server that then can respond with a subset of contents. On server response you can create an array of contents that adhere to the Delight VR json spec (see below) and pass them as an argument to the contentCallback function.

on-request-content-count=”<function(filters, contentCountCallback)>”
This function will be called when the hub needs to know the item count for a specific subset of the contents. This is used to build up pagination and other related things. When the server responds with the count just pass that as an argument to the contentCountCallback function.

The Delight VR JSON/Object Spec

To support dynamically adding contents when the dl8-hub-content mode is dynamic you need to pass an array of contents to the contentCallback function in the on-request-content handler. The data passed to this callback must adhere to the Delight VR Object specification. Here is an example of how a <dl8-video> element with two sources would look like:

  tagName: "dl8-video",
  title: "Example Video",
  poster: "example-poster.jpg",
  format: "STEREO_360_TB",
  _children: [{
    tagName: "source",
    src: "example-low.mp4",
    type: "video/mp4",
    quality: "low"
  }, {
    tagName: "source",
    src: "example-high.mp4",
    type: "video/mp4",
    quality: "high"

Generally a content is always described by the tagName, all subsequent attributes and optional children tags adhering to the same spec recursively in the _children property. Below you will find a description of the format:

<data> = {
  tagName: <a-valid-dl8-content-tag>,
  opt <attrNameInCamelCase>: <string>, // NOTE: camel case will be
  // converted to attribute
  // notation:
  // forExample -> for-example
  opt _children: [ // NOTE: recursive nesting is 
    // possible

Filter and sorter API

When the on-request-content and on-request-content-count handlers are called, your JavaScript function will be given a filters and a sorter argument. These arguments are arrays of filterIds or sorterIds that you can use to identify your filter and sorter objects to formulate a backend query.


The <dl8-hub-group> is a meta element that can group contents by defining actions (filtering, sorting) that are triggered when interacting with it. Like a menu item that can appear amidst contents in a content widget.

<dl8-hub-group title="Music" poster="poster.jpg">
  <dl8-hub-action-filter for="main" filter="musicFilter">


The <dl8-hub-filter> is a grouping element for all available filters. Filters are means to filter content according to content types, existing content attributes or even freely definable content attributes (x-attrs). They can be referenced by <dl8-hub-action-filter> actions. Each filter has a filter-id attribute to reference it and a value attribute to tell the system what should be filtered as well as a name attribute. The name attribute must be provided if the filter is displayed to the user (done through the dl8-hub-grid filter-list array). Attribute filter additionally have a attr attribute to declare over which content attribute to filter. Given that you are using the dynamic content mode you can use the <dl8-hub-filter-dynamic> to reference remote implementations. Possible child elements of <dl8-hub-filter> are:

filter-id=”<string>” attr=”<string>” value=”<string>” name=”<string>”
filter-id=”<string>” attr=”<string>” value=”<string>” name=”<string>”
filter-id=”<string>” attr=”<string>” value=”<array>” name=”<string>”
filter-id=”<string>” attr=”<string>” value=”<array>” name=”<string>”
filter-id=”<string>” value=”<string>” name=”<string>”
filter-id=”<string>” value=”<array>” name=”<string>”
filter-id=”<string>” name=”<string>”

This for example can be used in combination with a <dl8-hub-group> element to define a grid tile that, upon interacting, filters the grid view to only show videos:


 <dl8-video ...></dl8-video>
 <dl8-img ...></dl8-img>
 <dl8-hub-group title="Videos" poster="poster.jpg">
 <dl8-hub-action-filter for="main" filter="videoFilter">

 <dl8-hub-filter-element-is filter-id="videoFilter" value="dl8-video">

 <dl8-hub-grid view-id="main"></dl8-hub-grid>



This is a grouping element for all sorters. Sorter are means to sort content over freely defined content attributes. Sorter and Filter have lot in common. Both can be referenced by actions via the sorter-id and define the attribute over which to sort with the attr attribute. Sorting can either be done lexicographical or numerical. This is defined by the type attribute. Given you are working in a dynamic query mode (see above for details) you can use the dl8-hub-sorter-dynamic to reference your remote server implementation of a sort. Currently the following sorter are available:

sorter-id=”<string>” attr=”<string>” type=”<lexicographical|numerical>”


The vizor groups all children widget elements and lays them out horizontally on a virtual cylinder around the user. It does so by centering all widgets along the resting position (negative z-axis) and stretching widgets out vertically so they fill up the height of the vizor. It currently is the only available layout system for the hub. You can set the following attributes:

height=”<number>” (optional)

radius=”<number”> (optional)

spacing=”<number>” (optional)

show-brand-logo (boolean, optional)

show-home-button (boolean, optional)

no-shadow  (boolean, optional)


The grid is one of two currently available widgets. It is the main view for displaying content. It displays cover items with thumbnails and labels in a regular grid view with freely definable column and row count and can be paginated when not all items fit one page. The pagination can either be vertically or horizontally. The view can be filtered and sorted by default through setting filter and sorter attributes respectively. You can also provide a tag filtering system for the user by setting the filter-list value to a custom defined array. Each value must refer to an existing dl8-hub-filter.

As a bonus the grid can have a sorter dropdown by providing a sorter-list so the user can choose the ordering of the displayed contents. Possible attributes are:

title=”<string”> (optional)

view-id=”<string>” (optional)

width=”<number>” (optional)

rows=”<number>” (optional)

columns=”<number>” (optional)

tile-padding-x=”<number>” (optional)

tile-padding-y=”<number>” (optional)

scroll-mode=”<vertical|horizontal>” (optional)

show-no-cover-text (boolean, optional)

filter=”<filter-id>” (optional)

sorter=”<sorter-id”> (optional)

sorter-list=”<array>” (optional)

filter-list=”<array>” (optional)


The menu widget displays <dl8-menu-item> child elements in a vertical scrolling list. Menu items just like hub groups can trigger multiple actions (filter actions, sorter actions, etc.). The menu has the following attributes:

title=”<string”> (optional)

view-id=”<string”> (optional)

width=”<number”> (optional)

rows=”<string”> (optional)

default-menu-item=”<menu-item-id>” (optional)


A menu item is a text button that upon interaction triggers the declared child action elements. It has the following attributes:


menu-item-id=”<string”> (optional)

The Action System

As mentioned in the markup section, triggerable elements (<dl8-hub-group>, <dl8-hub-menu-item>) can declare action elements as children which are executed in order of appearance when a user interacts with these. There are different types of actions. Currently there are 3 types: filter actions, sorter actions and set-title actions. The action system is build in a way that novel actions can easily be introduced so that greater flexibility and interactivity of the hub can be achieved in the future.

The currently supported actions are:


This action triggers a filter on a specified view




This action triggers a sort operation on a specified view




This action triggers a title change on a specified view




Three column layout

This is a full blown hub with a menu, a full size grid and a small side grid for special items

 <dl8-hub title="Three Columns" room-src="room.jpg" room-format="STEREO_360_TB">

  <!-- Contents -->
    <dl8-model poster="model-poster.jpg" title="Model" src="model.json">
      <dl8-model-ibl src="ibl/forest.json"></dl8-model-ibl>
      <dl8-model-skybox src="forest.png"></dl8-model-skybox>
    <dl8-video title="Video 1" poster="video-poster1.jpg" format="MONO_360" x-dl8-attr-category="Music" x-dl8-attr-rating="1.0" x-dl8-attr-ts="123456778">
      <source src="video1.mp4" type="video/mp4" />
    <dl8-video title="Video 2" poster="video-poster2.jpg" format="STEREO_360_TB" x-dl8-attr-category="Animation" x-dl8-attr-rating="4.0" x-dl8-attr-ts="123456782">
      <source src="video2.mp4" type="video/mp4" />
    <dl8-video title="Video 3" poster="video-poster3.jpg" format="STEREO_360_TB" x-dl8-attr-category="Animation" x-dl8-attr-rating="4.0" x-dl8-attr-ts="123456782">
      <source src="video3.mp4" type="video/mp4" />
    <dl8-img title="Photo 1" poster="photo-poster1.jpg" src="photo1.vr.jpg" format="CARDBOARD_PHOTO" x-dl8-attr-category="Photo" x-dl8-attr-tags="[ 'sunny', 'cloudy' ]" x-dl8-attr-rating="8.0" x-dl8-attr-ts="123456781">
    <dl8-img title="Photo 2" poster="photo-poster2.jpg" src="photo2.jpg" format="MONO_360" x-dl8-attr-category="Photo" x-dl8-attr-tags="[ 'sunny', 'cloudy' ]" x-dl8-attr-rating="8.0" x-dl8-attr-ts="1234567811">
    <dl8-hub-group title="Music" poster="music-cover.jpg">
      <dl8-hub-action-filter for="main" filter="categoryMusicFilter"></dl8-hub-action-filter>
      <dl8-hub-action-set-title for="main" value="Category: Music"></dl8-hub-action-set-title>
    <dl8-hub-group title="Photo" poster="photo-cover.jpg">
      <dl8-hub-action-filter for="main" filter="categoryPhotoFilter"></dl8-hub-action-filter>
      <dl8-hub-action-set-title for="main" value="Category: Photo"></dl8-hub-action-set-title>
    <dl8-hub-group title="Animation" poster="animation-cover.jpg">
      <dl8-hub-action-filter for="main" filter="categoryAnimationFilter"></dl8-hub-action-filter>
      <dl8-hub-action-set-title for="main" value="Category: Animation"></dl8-hub-action-set-title>
    <dl8-hub-group title="All Groups" poster="all-cover.jpg">
      <dl8-hub-action-filter for="main" filter="groupFilter"></dl8-hub-action-filter>
      <dl8-hub-action-set-title for="main" value="Category: All Groups"></dl8-hub-action-set-title>

  <!-- Visual Representation -->
  <dl8-hub-vizor brand-src="brand-logo.jpg" height="0.7" spacing="0.05">
    <dl8-hub-menu width="0.3" title="Home" default-menu-item="all" rows="10">
      <dl8-hub-menu-item menu-item-id="all" title="All">
        <dl8-hub-action-filter for="main" filter="allContentFilter"></dl8-hub-action-filter>
        <dl8-hub-action-set-title for="main" value="All"></dl8-hub-action-set-title>
      <dl8-hub-menu-item title="Videos">
        <dl8-hub-action-filter for="main" filter="videosFilter"></dl8-hub-action-filter>
        <dl8-hub-action-set-title for="main" value="Videos"></dl8-hub-action-set-title>
      <dl8-hub-menu-item title="Images">
        <dl8-hub-action-filter for="main" filter="imagesFilter"></dl8-hub-action-filter>
        <dl8-hub-action-set-title for="main" value="Images"></dl8-hub-action-set-title>
      <dl8-hub-menu-item title="Music">
        <dl8-hub-action-filter for="main" filter="categoryMusicFilter"></dl8-hub-action-filter>
        <dl8-hub-action-set-title for="main" value="Music"></dl8-hub-action-set-title>
      <dl8-hub-menu-item title="Best Images">
        <dl8-hub-action-filter for="mostRecentList" filter="imagesFilter"></dl8-hub-action-filter>
        <dl8-hub-action-set-title for="mostRecentList" value="Best Images"></dl8-hub-action-set-title>
      <dl8-hub-menu-item title="Best Videos">
        <dl8-hub-action-filter for="mostRecentList" filter="videosFilter"></dl8-hub-action-filter>
        <dl8-hub-action-sort for="mostRecentList" sorter="timestampSorter"></dl8-hub-action-sort>
        <dl8-hub-action-set-title for="mostRecentList" value="Best Videos"></dl8-hub-action-set-title>
      <dl8-hub-menu-item title="Popular Videos">
        <dl8-hub-action-filter for="mostRecentList" filter="videosFilter"></dl8-hub-action-filter>
        <dl8-hub-action-sort for="mostRecentList" sorter="ratingSorter"></dl8-hub-action-sort>
        <dl8-hub-action-sort for="mostRecentList" sorter="timestampSorter"></dl8-hub-action-sort>
        <dl8-hub-action-set-title for="mostRecentList" value="Popular Videos"></dl8-hub-action-set-title>
    <dl8-hub-grid filter-list="['categoryMusicFilter','categoryAnimationFilter','categoryPhotoFilter']" view-id="main" width="1.0" scroll-mode="horizontal" columns="3" rows="3" title="Main" filter="allContentFilter" sorter="alphabeticalSorter"></dl8-hub-grid>
    <dl8-hub-grid view-id="mostRecentList" width="0.3" scroll-mode="vertical" columns="1" rows="3" title="Most Recent" filter="allContentFilter" sorter="timestampSorter" show-no-cover-text></dl8-hub-grid>

  <!-- Filters -->
    <dl8-hub-filter-attr-is filter-id="categoryMusicFilter" attr="x-dl8-attr-category" value="Music" name="Music"></dl8-hub-filter-attr-is>
    <dl8-hub-filter-attr-is filter-id="categoryAnimationFilter" attr="x-dl8-attr-category" value="Animation" name="Animation"></dl8-hub-filter-attr-is>
    <dl8-hub-filter-attr-is filter-id="categoryPhotoFilter" attr="x-dl8-attr-category" value="Photo" name="Photo"></dl8-hub-filter-attr-is>
    <dl8-hub-filter-attr-contains-one-of filter-id="tagFilterCloudyOr" attr="x-dl8-attr-tags" value="[ 'cloudy', 'sunny' ]"></dl8-hub-filter-attr-contains-one-of>
    <dl8-hub-filter-attr-contains-all-of filter-id="tagFilterCloudyAnd" attr="x-dl8-attr-tags" value="[ 'cloudy', 'sunny' ]"></dl8-hub-filter-attr-contains-all-of>
    <dl8-hub-filter-attr-contains filter-id="tagFilterSunny" attr="x-dl8-attr-tags" value="sunny"></dl8-hub-filter-attr-contains>
    <dl8-hub-filter-element-is filter-id="videosFilter" value="dl8-video"></dl8-hub-filter-element-is>
    <dl8-hub-filter-element-is filter-id="imagesFilter" value="dl8-img"></dl8-hub-filter-element-is>
    <dl8-hub-filter-element-is-one-of filter-id="groupFilter" value="[ 'dl8-hub-group' ]"></dl8-hub-filter-element-is-one-of>
    <dl8-hub-filter-element-is-one-of filter-id="allContentFilter" value="[ 'dl8-model', 'dl8-img', 'dl8-video', 'dl8-hub-group' ]"></dl8-hub-filter-element-is-one-of>
    <dl8-hub-filter-element-is filter-id="menuFilter" value="dl8-hub-menu-filter"></dl8-hub-filter-element-is>

  <!-- Sorter -->
    <dl8-hub-sorter-attr sorter-id="alphabeticalSorter" attr="title" type="lexicographical" order="ascending"></dl8-hub-sorter-attr>
    <dl8-hub-sorter-attr sorter-id="ratingSorter" attr="x-dl8-attr-rating" type="numerical" order="descending"></dl8-hub-sorter-attr>
    <dl8-hub-sorter-attr sorter-id="timestampSorter" attr="x-dl8-attr-ts" type="numerical" order="descending"></dl8-hub-sorter-attr>
    <dl8-hub-sorter-attr sorter-id="timestampSorter2" attr="x-dl8-attr-ts" type="numerical" order="ascending"></dl8-hub-sorter-attr>