Fork me on GitHub

Structured Data Guide

Overview

Schema.org contains a rich vocabulary that can be used to help tools read and understand web pages in wide number of domains. This page details the markup that can be added to a hotel website for the benefit of not only Triptease products but also your SEO and Google listings.

If you notice anything wrong please raise an issue.

Microdata vs RDFa vs JSON-LD

If the markup is static (like your hotel name and address) then JSON-LD is generally the easiest to test and debug, while if the meta data is more dynamic (like offers or rate details) you may want to use the microdata format embedded in the HTML so that you keep the UI in sync with the meta data.

Triptease supports all three formats so if you are already using one then don’t worry about switching.

Handling data updates

If you are an SPA (Single Page App) or support multiple updates on the same page (i.e. searches), please update the HTML/JSON in place. Do NOT keep adding additional elements as this will just corrupt the data.

Validating your code

You can use schema.org’s validator to check the output of your structured data and fix any errors.

A common error to watch out for is trailing commas in JSON-LD.

Getting started

There are different levels of support for meta-data, it’s best to start with the simplest and work your way up to more advanced features as you get more comfortable.

Advanced

Identification

If you are already using another form of identification (apiKeys, propertyCodes etc) then you can safely skip this step

This is the simplest and most important meta data you can add through out your marketing website and booking engine. Ideally you want this on every page that represents a single hotel. Doing this will automatically allow your hotel to appear on Google search pages and Google Maps. Just putting the hotel name and @type on each page will help Triptease identify your hotel automatically

JSON-LD Example

<script type="application/ld+json">
{
 "@context": "http://schema.org",
 "@type": "Hotel",
 "name": "Sea View Hotel",
 "identifier": "1234567",
 "brand": "Great Escapes",
 "address": 
  {
  "@type": "PostalAddress",
  "streetAddress": "1 Piccadilly",
  "addressLocality": "St. James's",
  "addressRegion": "London",
  "postalCode": "W1 9B",
  "addressCountry": "United Kingdom"
  },
  "geo": {
      "@type": "GeoCoordinates",
      "latitude": "15.234",
      "longitude": "-80.3242"
  },
 "telephone": "+44 1234 5678",
 "image": "http://example.com/image.png",
 "url": "http://example.com/"
}
</script>

Microdata Example

<div itemscope itemtype="http://schema.org/Hotel">
    <h1 itemprop="name">Sea View Hotel</h1>
    <span itemprop="identifier">123456</span>
    <h2 itemprop="brand">Great Escapes</h1>
    <div itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">
        <span itemprop="streetAddress">1 Piccadilly</span>
        <span itemprop="addressLocality">St. James's</span>
        <span itemprop="addressRegion">London</span>
        <span itemprop="postalCode">W1 9B</span>
        <span itemprop="addressCountry">United Kingdom</span>
    </div>
     <div itemprop="geo" itemscope itemtype="http://schema.org/GeoCoordinates">
        latitude:<span itemprop="latitude">15.234</span>, 
        longitude:<span itemprop="longitude">-80.3242</span>
    </div>
 <div>Telephone: <span itemprop="telephone">+44 1234 5678</span></div>
 <div>
    <a href="http://example.com/" itemprop="url">
        <img itemprop="image" src="http://example.com/image.png"/>
    </a>
 </div>
</div>

Let’s walk through this:

@type

Make sure you set this to Hotel, LodgingBusiness or BedAndBreakfast rather than the more generic WebSite, LocalBusiness or Organization. (Use Organization in a separate metadata block to describe your parent organisation or group if needed)

Used by: Google, Triptease

name

The name should be a unique name within your group or brand.

Used by: Google, Triptease

identifier (Optional)

The identifier should be a unique property code for your hotel.

Used by: Triptease

brand (Optional)

The brand can help Triptease group your hotels together.

Used by: Triptease

address (Optional)

The address allows Triptease and Google to correctly associate your Hotel with it’s location. At a minimum add the postalCode and addressCountry.

Used by: Google, Triptease

geo (Optional)

The geo allows Triptease and Google to accurately display your Hotel on a map.

Used by: Google, Triptease

telephone (Optional)

The telephone will allow Google to correctly list your contact details

Used by: Google

url (Optional)

The url will allow Triptease and Google to link to your hotel home page.

Used by: Google, Triptease

image (Optional)

The image will allow Google (Search and Maps) to display a thumbnail image next to your name

Used by: Google

Reservation

After identifying the hotel, the next-most important data you can provide is the reservation information after a customer completes their booking. If you support multi room booking just repeat the script tag or itemScope root element (use an array in JSON-LD).

Used by: Triptease

JSON-LD Example

<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "LodgingReservation",
  "reservationId": "abc456",
  "reservationStatus": "http://schema.org/ReservationConfirmed",
  "checkinTime": "2017-04-11T16:00:00-00:00",
  "checkoutTime": "2017-04-13T11:00:00-00:00",
  "totalPrice": "800.00",
  "basePrice": "750.00",
  "priceCurrency": "GBP",
  "offerCode": ["AA"],
  "provider": {
    "@type": "Hotel",
    "name": "Sea View Hotel",
    "identifier": "1234567",
    "brand": "Great Escapes"
  }
}
</script>

Microdata Example

<div itemscope itemtype="http://schema.org/LodgingReservation">
    <h1>Reservation #<span itemprop="reservationId">abc456</span></h1>
    <h2>Details</h2>
    <dl>
        <dt>Status</dt>
        <dd itemprop="reservationStatus" content="http://schema.org/ReservationConfirmed">Confirmed</dd>
        <dt>Checkin</dt>
        <dd itemprop="checkinTime" content="2017-04-11T16:00:00-00:00">On 11th April from 4pm</dd>
        <dt>Checkout</dt>
        <dd itemprop="checkoutTime" content="2017-04-13T11:00:00-00:00">On 13th April by 11am</dd>
        <dt>Total</dt>
        <dd><span itemprop="totalPrice">800.00</span> <span itemprop="priceCurrency">GBP</span></dd>
        <dd><span itemprop="basePrice">750.00</span> <span>GBP</span></dd>
        <dt>Promotion/Discount</dt>
        <dd><span itemprop="offerCode"/>AA</span></dd>
    </dl>
    <div itemprop="provider" itemscope itemtype="http://schema.org/Hotel">
        <span itemprop="name">Sea View Hotel</span>
        <meta itemprop="identifier" content="8901234">
        <div itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">
            <span itemprop="streetAddress">1 Piccadilly</span>
            <span itemprop="addressLocality">St. James's</span>
            <span itemprop="addressRegion">London</span>
            <span itemprop="postalCode">W1 9B</span>
            <span itemprop="addressCountry">United Kingdom</span>
        </div>
        <span itemprop="telephone">+44 1234 5678</span>
    </div>
</div>

Let’s walk through this:

@type

Set this to LodgingReservation

reservationId

The reservationId should be unique and verifiable.

reservationStatus

The reservationStatus should be set to ReservationConfirmed. If you wish to expose reservations earlier in the funnel then make sure you use one of the other ReservationStatusType. If you support cancellations please also add the correct structured data to that page and change the reservationStatus to ReservationCancelled

checkinTime

Triptease requires checkinTime to be a date in ISO 8601 format without time or timezone e.g. 2021-10-12. NB: This deviates from the specification as we have consistently seen incorrect dates provided due to timezone adjustments. Any time or timezone will be ignored.

checkoutTime

Triptease requires checkoutTime to be a date in ISO 8601 format without time or timezone e.g. 2021-10-13. NB: This deviates from the specification as we have consistently seen incorrect dates provided due to timezone adjustments. Any time or timezone will be ignored.

totalPrice

The totalPrice is the total price for the duration of the stay including taxes etc. It does not include the currency symbol.

basePrice (Optional)

The basePrice is the base price for the duration of the stay excluding taxes etc. It does not include the currency symbol.

priceCurrency

The priceCurrency is the three digit ISO currency code.

offerCode (Optional)

Offer can either be a string or array of strings. It should be used any time the offers have been filtered or the price changed due to the user apply any of the following: promo/discount/group/corporation/government/agency/rate/room code.

*A Triptease extension

provider (Optional)

The provider field should be set to the Hotel, LodgingBusiness or BedAndBreakfast to which the individual reservation applies.

When not provided, it defaults to the hotel in Identification section.

Used by: Triptease

These are the parameters the customer searched with. schema.org does not directly model these concepts so TripTease has made a small extension to capture these additional parameters while trying to keep to the same naming conventions and domain language.

JSON-LD Example

<script type="application/ld+json">
{
  "@context": "https://structured-data.triptease.io",
  "@type": "LodgingSearch",
  "checkinTime": "2017-04-11T12:00:00-00:00",
  "checkoutTime": "2017-04-13T12:00:00-00:00",
  "numAdults": "2",
  "numChildren": "0",
  "numRooms": "1",
  "offerCode": ["AA"] 
}
</script>

Microdata Example

<div itemscope itemtype="https://structured-data.triptease.io/LodgingSearch">
    <meta itemprop="checkinTime" content="2017-04-11T12:00:00-00:00"/>
    <meta itemprop="checkoutTime" content="2017-04-13T12:00:00-00:00"/>
    <meta itemprop="numAdults"  content="2"/>
    <meta itemprop="numChildren" content="0"/>
    <meta itemprop="numRooms" content="1"/>
    <meta itemprop="offerCode" content="AA"/>
</div>

Let’s walk through this:

@context

Set this to https://structured-data.triptease.io

@type

Set this to LodgingSearch*

checkinTime

Triptease requires checkinTime to be a date in ISO 8601 format without time or timezone e.g. 2021-10-12. NB: This deviates from the specification as we have consistently seen incorrect dates provided due to timezone adjustments. Any time or timezone will be ignored.

checkoutTime

Triptease requires checkoutTime to be a date in ISO 8601 format without time or timezone e.g. 2021-10-13. NB: This deviates from the specification as we have consistently seen incorrect dates provided due to timezone adjustments. Any time or timezone will be ignored.

numAdults (Optional)

The numAdults is the total number of adults that were searched for. Defaults to 2

numChildren (Optional)

The numChildren is the total number of children that were searched for. Defaults to 0

numRooms (Optional)

The numRooms* is the total number of rooms that were searched for. Defaults to 1

numRooms should not be present unless the search results could show a different price to what a guest would pay if they were only booking one room (e.g. a user searches for 3 rooms and the prices displayed are for the total of all 3 rooms)

offerCode (Optional)

Offer can either be a string or array of strings. It should be used any time the offers have been filtered or the price changed due to the user apply any of the following: promo/discount/group/corporation/government/agency/rate/room code.

*A Triptease extension

Offers for Hotel Rooms

Used by: Triptease

These are the offer or rooms and rates the hotel has available for the specified search parameters. schema.org models this around offers for hotel rooms. This image explains the concept:

Schema Diagram showing the relationship between entities

Multiple offers can be added to a page either inside a single script tag containing an array or multiple script/div tags etc.

JSON-LD Example

<script type="application/ld+json">
[
  {
    "@context": "http://schema.org/",
    "@type": "Offer",
    "itemOffered": {
      "@type": "HotelRoom",
      "name": "Deluxe Double",
      "identifier": "DD-001"
    },
    "name": "Best Available Rate",
    "identifier": "BAR-001",
    "priceSpecification": {
      "@type": "UnitPriceSpecification",
      "price": "99.00",
      "priceCurrency": "USD",
      "unitText": "Nightly"
    },
    "offeredBy": {
      "@type": "Hotel",
      "name": "Sea View Hotel",
      "identifier": "1234567",
      "brand": "Great Escapes"
    }
  },
  {
    "@context": "http://schema.org/",
    "@type": "Offer",
    "itemOffered": {
      "@type": "HotelRoom",
      "name": "Deluxe Double",
      "identifier": "DD-001"
    },
    "name": "Member Rate",
    "identifier": "MER-001",
    "priceSpecification": {
      "@type": "UnitPriceSpecification",
      "price": "88.00",
      "priceCurrency": "USD",
      "unitText": "Nightly"
    },
    "offeredBy": {
      "@type": "Hotel",
      "name": "Garden View Hotel",
      "identifier": "8901234",
      "brand": "Great Escapes"
    }
  }
]
</script>

Microdata Example

<div itemscope itemtype="http://schema.org/Offer">
  <div itemprop="itemOffered" itemscope itemtype="http://schema.org/HotelRoom">
      <span itemprop="name">Deluxe Double</span>
      <meta itemprop="identifier" content="DD-001">
  </div>
  <span itemprop="name">Best Available Rate</span>
  <meta itemprop="identifier" content="BAR-001">
  <span itemprop="priceSpecification" itemscope itemtype="http://schema.org/UnitPriceSpecification">
    <meta itemprop="price" content="99.00">$99.00
    <meta itemprop="priceCurrency" content="USD">
    <meta itemprop="unitText" content="Nightly">per night
  </span>
  <span itemprop="offeredBy" itemscope itemtype="http://schema.org/Hotel">
    <span itemprop="name">Sea View Hotel</span>
    <meta itemprop="identifier" content="123456">
    <span itemprop="brand">Great Escapes</span>
  </span>
</div>

Let’s walk through this:

@type

Set this to Offer

itemOffered

The itemOffered should link to a HotelRoom with a room name or type and optional identifier for the room code.

name

The name should contain the rate name

identifier (Optional)

The identifier can be used to set a rate code

priceSpecification

The priceSpecification contains the price and currency:

price: The numeric value of the offer

currency: The 3 character currency code of the offer

unitText (optional): “Total” if the price is for the entire stay. “Nightly” if the price is per night. Defaults to “Nightly”.

offeredBy (Optional)

The offeredBy field should be set to the Hotel, LodgingBusiness or BedAndBreakfast to which the individual offer applies.

When not provided, it defaults to the hotel in Identification section.

Advanced

No availability

Used by: Triptease

This allows you to tell us you don’t have any availability for the search that was just performed. The search should be provided using LodgingSearch.

This is applicable even if you display availability for alternative dates or alternative properties. Note that the LodgingSearch should be the original search that was performed.

JSON-LD Example

<script type="application/ld+json">
{
  "@context": "http://schema.org/",
  "@type": "OfferCatalog",
  "numberOfItems": 0
}
</script>

Microdata Example

<div itemscope itemtype="http://schema.org/OfferCatalog">
 <meta itemprop="numberOfItems" content="0"> 
 No availaible rooms for the dates you searched
</div>

Let’s walk through this:

@type

Set this to OfferCatalog

numberOfItems

Just set this to zero, so we know you have no availability. See https://schema.org/numberOfItems

Application Details

Used by: Triptease

This allows you to tell us about your booking engine or marketing site. This is used purely for diagnosis

JSON-LD Example

<script type="application/ld+json">
{
  "@context": "http://schema.org/",
  "@type": "SoftwareApplication",
  "name": "AwesomeBookingEngine",
  "version" "12.43"
}
</script>

Microdata Example

<div itemscope itemtype="http://schema.org/SoftwareApplication">
 Powered by <span itemprop="name">AwesomeBookingEngine</span> Version: <span itemprop="version">12.43</span> 
</div>

Let’s walk through this:

@type

Set this to SoftwareApplication

name

The name should contain the booking engine name. The format is alphanumeric, single-word only (e.g. QuickRez) .

version

The version should contain the booking engine version

Further Reading

Leverage structured data to turbo-drive your click-through rate

Markup for Hotels

Understand how structured data works

Structured Data Testing Tool

Schema.org Generator

Schema Markup Generator

Microdata

Help

If you are having trouble then do reach out to your Customer Success Manager or Direct Booking Coach.