Cookbook/Books

Marking-Up Book Data with GoodRelations

Note: Parts of this recipe are already using new schema.org elements from the upcoming integration of GoodRelations elements into schema.org.

Overview

This page describes how you can mark-up book item pages using GoodRelations or schema.org. The full background of modeling such data is given towards the end of the document. For a quick start, you need to understand the following:

  1. A book can be either a real, physical book copy (e.g. when you offer it for sale) or a book title (i.e. a prototype or datasheet of a mass-produced book, e.g. a bibliographic entry in a library catalog).
  2. When publishing bibliographic entries, you typically model only the book title.
  3. When publishing book offers, you model the book copy (the product) and the offer (the promise to sell the book for a certain amount of money). In those cases, you have to create to main entities, the book and the offer. A typical mistake is to try to attach commercial aspects directly to the book.
  4. GoodRelations can be used directly in RDFa syntax or (soon) directly from the schema.org namespace as extensions to the schema.org elements. There are slight differences in naming. See here for more information on GoodRelations and schema.org.

Examples

Example: Book Title (Bibliographic Data)

RDFa Syntax in the GoodRelations Namespace

<div typeof="schema:Book gr:ProductOrServiceModel" itemid="#product>
  <div property="gr:name">HTML for Idiots</div>
  <link rel="schema:author" resource="http://dbpedia.org/resource/Karl_May" />
  <link rel="schema:bookFormat" resource="http://schema.org/Hardcover" />
  ISBN: <span property="schema:isbn">1234567890123</span>
...other properties from schema:Book or gr:SomeItems ...
</div>

Microdata Syntax in the Schema.org Namespace

<div itemscope itemtype="http://schema.org/Book" itemid="#product">
  <link itemprop="additionalType" href="http://schema.org/ProductModel" />
  <span itemprop="name">HTML for Idiots</span>
  Author: <link itemprop="author" resource="http://dbpedia.org/resource/Karl_May" />Karl May
  Format: <link itemprop="bookFormat" resource="http://schema.org/Hardcover" />Hardcover
  ISBN: <span itemprop="isbn">1234567890123</span>
</div>

Note: In theory, the itemtype and the additionalType values could be swapped, but not all schema.org parsers will consider the additionalType property, so put the more important information into the main itemtype. Also, this influences which properties you can attach. Since we want to use properties from http://schema.org/Book, we have to use this type for the main itemtype.

Example: Book Offer - Individual Copy (e.g. eBay)

RDFa Syntax in the GoodRelations Namespace

<div typeof="gr:Offering" about="#offer">
  <div property="gr:name">HTML for Idiots - Used Copy, $ 9.99</div>
  <link rel="gr:hasBusinessFunction" resource="http://purl.org/goodrelations/v1#Sell" />
  <div rel="gr:hasPriceSpecification">
    <div typeof="gr:UnitPriceSpecification">Price:
     <span property="gr:hasCurrency" content="USD">$</span>
     <span property="gr:hasCurrencyValue" datatype="xsd:float">9.99</span>
     <div property="gr:validThrough" datatype="xsd:dateTime"
          content="2012-11-30T23:59:59Z"></div>
    </div>
  </div>
  <div rel="gr:includes">
    <div typeof="schema:Book gr:Individual" itemid="#product>
        <div property="gr:name">HTML for Idiots</div>
        <link rel="schema:author" resource="http://dbpedia.org/resource/Karl_May" />
        <link rel="schema:bookFormat" resource="http://schema.org/Hardcover" />
        ISBN: <span property="schema:isbn">1234567890123</span>
        ...other properties from schema:Book or gr:SomeItems ...
        Condition: <div property="gr:condition>used</div>
    </div>
  </div>
</div>

Microdata Syntax in the Schema.org Namespace

<div itemscope itemtype="http://schema.org/Offer" itemid="#offer">
  <div itemprop="name">HTML for Idiots - Used Copy, $ 9.99</div>
  <link itemprop="businessFunction"
        href="http://purl.org/goodrelations/v1#Sell" />
  <div itemscope itemprop="priceSpecification"
       itemtype="http://schema.org/UnitPriceSpecification">Price:
    <meta itemprop="priceCurrency" content="USD">$
    <span itemprop="price">9.99</span>
    <meta itemprop="validThrough" content="2012-11-30T23:59:59Z" />
  </div>
  <div itemprop="itemOffered" itemscope itemtype="http://schema.org/Book" itemid="#product">
    <link itemprop="additionalType" href="http://schema.org/IndividualProduct" />
    <span itemprop="name">HTML for Idiots</span>
    Author: <link itemprop="author" resource="http://dbpedia.org/resource/Karl_May" />Karl May
    Format: <link itemprop="bookFormat" resource="http://schema.org/Hardcover" />Hardcover
    ISBN: <span itemprop="isbn">1234567890123</span>
</div>

Note: In theory, the itemtype and the additionalType values could be swapped, but not all schema.org parsers will consider the additionalType property, so put the more important information into the main itemtype. Also, this influences which properties you can attach. Since we want to use properties from http://schema.org/Book, we have to use this type for the main itemtype.

Example: Book Offer, Multiple New Copies (e.g. Amazon)

RDFa Syntax in the GoodRelations Namespace

<div typeof="gr:Offering" about="#offer">
  <div property="gr:name">HTML for Idiots - $ 19.99 per copy</div>
  <link rel="gr:hasBusinessFunction" resource="http://purl.org/goodrelations/v1#Sell" />
  <div rel="gr:hasPriceSpecification">
    <div typeof="gr:UnitPriceSpecification">Price:
     <span property="gr:hasCurrency" content="USD">$</span>
     <span property="gr:hasCurrencyValue" datatype="xsd:float">19.99</span>
     <div property="gr:validThrough" datatype="xsd:dateTime"
          content="2012-11-30T23:59:59Z"></div>
    </div>
  </div>
  <div rel="gr:includes">
    <div typeof="schema:Book gr:SomeItems" itemid="#product>
        <div property="gr:name">HTML for Idiots</div>
        <link rel="schema:author" resource="http://dbpedia.org/resource/Karl_May" />
        <link rel="schema:bookFormat" resource="http://schema.org/Hardcover" />
        ISBN: <span property="schema:isbn">1234567890123</span>
        ...other properties from schema:Book or gr:SomeItems ...
        Condition: <div property="gr:condition>new</div>
    </div>
  </div>
</div>

Microdata Syntax in the Schema.org Namespace

<div itemscope itemtype="http://schema.org/Offer" itemid="#offer">
  <div itemprop="name">HTML for Idiots - $ 19.99 per copy</div>
  <link itemprop="businessFunction"
        href="http://purl.org/goodrelations/v1#Sell" />
  <div itemscope itemprop="priceSpecification"
       itemtype="http://schema.org/UnitPriceSpecification">Price:
    <meta itemprop="priceCurrency" content="USD">$
    <span itemprop="price">19.99</span>
    <meta itemprop="validThrough" content="2012-11-30T23:59:59Z" />
  </div>
  <div itemprop="itemOffered itemscope itemtype="http://schema.org/Book" itemid="#product">
    <link itemprop="additionalType" href="http://schema.org/SomeProducts" />
    <span itemprop="name">HTML for Idiots</span>
    Author: <link itemprop="author" resource="http://dbpedia.org/resource/Karl_May" />Karl May
    Format: <link itemprop="bookFormat" resource="http://schema.org/Hardcover" />Hardcover
    ISBN: <span itemprop="isbn">1234567890123</span>
</div>

Note: In theory, the itemtype and the additionalType values could be swapped, but not all schema.org parsers will consider the additionalType property, so put the more important information into the main itemtype. Also, this influences which properties you can attach. Since we want to use properties from http://schema.org/Book, we have to use this type for the main itemtype.

Background Information

Books: Book titles vs. Book Copies

When we expose book data on the Web so that search engines and other computer-based services can process it, we have to be clear about the type of objects we are speaking, since the colloquial term "book" may represent two different types of objects:

  • A book title (as in the sentence "Peter Miller wrote the book 'HTML for Idiots'")

vs.

  • A book copy, i.e. an actual, physical book (as in the sentence "I am selling this copy of 'HTML for Idiots', which I used in class, and which has stains on pages 11 and 14").

So for instance, a publisher or a catalog with bibliographic data typically speaks about book titles, while an eBay page or online bookstore speaks about book copies.

Before you can markup book pages with GoodRelations, you have to be clear whether you are talking about book copies or book titles.

In fact, one can even it a third distinction, which is about disambiguating book titles into abstract pieces of creative work (e.g. "The Bible") vs. a particular manifestation thereof, like the King James Version of the Bible. We will not cover this in more detail in here, since for GoodRelations, both meanings of book titles can be treated using the same patterns.

Thinking About Products: Actual Products, Product Models, and Some Products

GoodRelations disambiguates the broad notion of a product into three different types of entities:

1. A real product, like my laptop, my car with this VIN and mileage, a particular item on an eBay auction. The important thing is that all information said about that product relates to the same entity.

The respective GoodRelations class is gr:Individual. (The upcoming schema.org type is http://schema.org/IndividualProduct as a subtype of http://schema.org/Product.)

Examples are the items on eBay auction pages or used cars.

2. A product model, i.e. a datasheet, like "Nikon T90", "iPod Nano 16 GB", or similar. This is basically the abstract definition of product features for mass-produced commodities. The nice thing is that if you are able to spot the link from a product to its product model, you can enrich the often shallow product description (e.g. from a shop page) with the rich feature data from the model page on the manufacturer's site.

In theory, there are at least two ways of modeling product models:

  • as abstract entities, e.g. subtypes of foaf:Document etc.
  • as prototypes, i.e. a special form of products.

GoodRelations treats product models as prototypes, since this allows using the same types (TV set, car, ...) and the same properties (weight, voltage,...) for products and product models alike, even though they mean different things for products vs. datasheets. (The weight of 5 kg for a TV set means that the TV set weighs 5 kg. The weight of 5 kg for a datasheet of a TV set means that each TV set of that make and model will, by default, weigh 5 kg.)

The respective GoodRelations class is gr:ProductOrServiceModel. (The upcoming schema.org type is http://schema.org/ProductModel.)

Examples are the product pages on manufacturers' sites, like Sony, Nikon, Volkswagen - the entities references are not products, but their blueprints.

3. Then we have a third case, in which the entities exposed on the Web are neither products nor product models, but instead "black boxes" of products, which themselves do not have a public identity. For example, an Amazon page for a new book does not expose publicly individual book copies, but just states that they have multiple ones on stock.

The main semantic difference is that multiple statements about the same entity do not imply that the statements refer to the same individual product. For instance, if you say that you bought that entity and that someone else bought it, too, it implies that you own books from the same bag of books, but not the same copy. (The identity criterion is different.)

The respective GoodRelations class is gr:SomeItems. (The upcoming schema.org type is http://schema.org/SomeProducts.)

These three subtypes are powerful, but it is of course also allowed to use the common abstraction gr:ProductOrService (in schema.org: http://schema.org/Product).

Modeling Book Copies and Book Titles

Now, modeling respective data using GoodRelations works by combining two classes per each product,

  • one class for the type of product, e.g. http://schema.org/Book for books, and
  • one class for distinguishing individual products (gr:Individual), product models (gr:ProductOrServiceModel), and bags of anonymous products (gr:SomeItems).

A Single Book Copy

<div typeof="schema:Book gr:Individual" itemid="#product>
  <div property="gr:name">HTML for Idiots</div>
...other properties from schema:Book or gr:Individual ...
</div>

A Book Title

<div typeof="schema:Book gr:ProductOrServiceModel" itemid="#product>
  <div property="gr:name">HTML for Idiots</div>
...other properties from schema:Book or gr:SomeItems ...
</div>

Some Books

<div typeof="schema:Book gr:SomeItems" itemid="#product>
  <div property="gr:name">HTML for Idiots</div>
...other properties from schema:Book or gr:SomeItems ...
</div>