RDFa with schema.org codelab: Cultural resources: LODLAM Toronto 2016

By Dan Scott,

About this codelab

In a previous exercise, you marked up a catalogue page with the schema.org vocabulary using RDFa attributes. In this exercise, you will focus on marking up the cultural resources held by your organization—in this case, library holdings—so that they can be recognized as Products with associated Offers by search engines (analogous to products available in online stores).

Audience: Intermediate

Prerequisites: To complete this codelab, you should already be familiar with HTML, RDFa, and schema.org. A previous exercise offers a practical introduction to those concepts.

Turning library holdings into Product

schema.org adopted the existing GoodRelations vocabulary as a way of expressing products and services that are available for sale. As it turns out, although some of the property and type names reflect a commercial bias, you can use the same vocabulary elements can to express non-commercial offers--such as the offer to lend a library resource to a patron.

In this exercise, you will turn the existing Book entity into a multi-typed entity by adding Product to the type declaration. This enables the described resource to satisfy properties expecting a value of either Book or Product, and also makes a union of the properties from those types available to further describe the resource.

View the page source HTML

Open book_step0.html in a text editor. You should see something like the following HTML source for the web page:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf8">
  <title>Deep work : rules for focused success in a distracted world
    : Newport, Cal, author.
    : Book, Regular Print Book
    : Toronto Public Library</title>

<meta property="og:title" content="Deep work : rules for focused success in a distracted world">
<meta property="og:type" content="book">
<meta property="og:image" content="http://syndetics.com/index.aspx?isbn=9781455586691/MC.gif">

<meta property="og:description" content="One of the most valuable skills in our
economy is becoming increasingly rare. ...--">

<meta property="og:url" content="http://tpl.ca/detail.jsp?Entt=RDM3339716&R=3339716">
<meta property="og:site_name" content="Toronto Public Library">

</head>
<body vocab="http://schema.org/" typeof="Book" resource="#book">
  <link property="sameAs" href="http://calnewport.com/books/deep-work/">
...
<h1 property="name">Deep work : rules for focused success in a distracted world</h1>
...

Note: In a pinch, you can use the browser development tools to view and edit the source of the web page (CTRL-Shift-i in Chrome or Firefox, in the Elements or Inspector tab respectively).

Add Product to the type declaration

Add Product to the typeof attribute in the <body> element. Check the results with one or more of the structured data testing tools.

You should see that both the Book and Product types are recognized. You may note, however, that Google's SDTT only recognizes the first declared type; this is a limitation of their tool and does not necessarily represent the results of their actual search engine.

Check your markup
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf8">
  <title>Deep work : rules for focused success in a distracted world
    : Newport, Cal, author.
    : Book, Regular Print Book
    : Toronto Public Library</title>

<meta property="og:title" content="Deep work : rules for focused success in a distracted world">
<meta property="og:type" content="book">
<meta property="og:image" content="http://syndetics.com/index.aspx?isbn=9781455586691/MC.gif">

<meta property="og:description" content="One of the most valuable skills in our
economy is becoming increasingly rare. ...--">

<meta property="og:url" content="http://tpl.ca/detail.jsp?Entt=RDM3339716&R=3339716">
<meta property="og:site_name" content="Toronto Public Library">

</head>
<body vocab="http://schema.org/" typeof="Book Product" resource="#book">
  <link property="sameAs" href="http://calnewport.com/books/deep-work/">
...
<h1 property="name">Deep work : rules for focused success in a distracted world</h1>
...

Declare each holding as a separate Offer

Products link to their offers via the offers property. The expected range of the offers property is an Offer entity.

Declare each holding in the catalog record as a separate Offer.

Check your markup
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf8">
  <title>Deep work : rules for focused success in a distracted world
    : Newport, Cal, author.
    : Book, Regular Print Book
    : Toronto Public Library</title>
</head>
<body vocab="http://schema.org/" typeof="Book Product" resource="#book">
  <link property="sameAs" href="http://calnewport.com/books/deep-work/">
...
<h1 property="name">Deep work : rules for focused success in a distracted world</h1>
...
      <table>
        <tbody><tr property="offers" typeof="Offer" resource="#offer1">
            <td>
              <b><a href="http://tpl.ca/detail.jsp?Nr=p_cat_branch_name:Agincourt">Agincourt</a></b>
            </td>
            <td>Book</td>
            <td>Due: 2/5/2016</td>
            <td>
              <span title="Means not available. Item is on loan
                to a customer. The person who has the item may return it by the
                date specified or keep it longer if the item can be
                renewed.">On loan</span>
            </td>
            <td>650.1 NEW</td>
          </tr>
          <tr property="offers" typeof="Offer" resource="#offer2">
            <td>
              <b><a href="http://tpl.ca/detail.jsp?Nr=p_cat_branch_name:Toronto%20Reference%20Library">Toronto Reference Library</a></b>
            </td>
            <td>Reference</td>
            <td>Bus Sci & Tech 3rd Fl Reference Careers</td>
            <td>
              <span title="Means available. Item is on the
                shelf at the library branch. Note: it's always a good idea
                to call the branch to confirm that the item is there.">In
                Library</span>
            </td>
            <td>650.1 NEW</td>
          </tr>
        </tbody></table>
---

Identify the seller, offer terms, and price of the Offer

While sellers of bibliographic items have a fairly clear mapping to Offer, the applicability for libraries is a bit less obvious. To express individual items that are available to purchase or borrow, begin by mapping your holding properties to Offer properties as follows:

Check your markup
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf8">
  <title>Deep work : rules for focused success in a distracted world
    : Newport, Cal, author.
    : Book, Regular Print Book
    : Toronto Public Library</title>
</head>
<body vocab="http://schema.org/" typeof="Book Product" resource="#book">
  <link property="sameAs" href="http://calnewport.com/books/deep-work/">
...
<h1 property="name">Deep work : rules for focused success in a distracted world</h1>
...
      <table>
        <tbody><tr property="offers" typeof="Offer" resource="#offer1">
            <td>
              <b><a href="http://tpl.ca/detail.jsp?Nr=p_cat_branch_name:Agincourt"
                    property="seller" typeof="Library"><span property="name">Agincourt</span></a>
              </b>
            </td>
            <td>Book
                <link property="businessFunction" href="http://purl.org/goodrelations/v1#LeaseOut">
                <meta property="price" content="0.00">
            </td>
            <td>Due: 2/5/2016</td>
            <td>
              <span title="Means not available. Item is on loan
                to a customer. The person who has the item may return it by the
                date specified or keep it longer if the item can be
                renewed.">On loan</span>
            </td>
            <td>650.1 NEW</td>
          </tr>
          <tr property="offers" typeof="Offer" resource="#offer2">
            <td>
              <b><a href="http://tpl.ca/detail.jsp?Nr=p_cat_branch_name:Toronto%20Reference%20Library"
                    property="seller" typeof="Library"><span property="name">Toronto Reference Library</span></a>
              </b>
            </td>
            <td>Reference
                <link property="businessFunction" href="http://tpl.ca/using-the-library/borrowing-materials/#referenceitems">
                <meta property="price" content="0.00">
            </td>
            <td>Bus Sci & Tech 3rd Fl Reference Careers</td>
            <td>
              <span title="Means available. Item is on the
                shelf at the library branch. Note: it's always a good idea
                to call the branch to confirm that the item is there.">In
                Library</span>
            </td>
            <td>650.1 NEW</td>
          </tr>
        </tbody></table>
---

Show the availability

The item holding status best maps to the availability property, which can take one of the following values:

If you have chosen to publicly display due dates in your system, you can also use the availabilityStarts property to provide an estimate of when the item will be available. The property expects a date/time value in ISO8601 format following the pattern YYYY-MM-DDThh:mm:ss (with an optional positive or negative time appended to indicate a time zone offset). Reminder: use the content attribute to supply the machine-readable counterparts for human-readable values.

Reflect the availability of each holding in the markup of the page.

Check your markup
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf8">
  <title>Deep work : rules for focused success in a distracted world
    : Newport, Cal, author.
    : Book, Regular Print Book
    : Toronto Public Library</title>
</head>
<body vocab="http://schema.org/" typeof="Book Product" resource="#book">
  <link property="sameAs" href="http://calnewport.com/books/deep-work/">
...
<h1 property="name">Deep work : rules for focused success in a distracted world</h1>
...
      <table>
        <tbody><tr property="offers" typeof="Offer" resource="#offer1">
            <td>
              <b><a href="http://tpl.ca/detail.jsp?Nr=p_cat_branch_name:Agincourt"
                    property="seller" typeof="Library"><span property="name">Agincourt</span></a>
              </b>
            </td>
            <td>Book
                <link property="businessFunction" href="http://purl.org/goodrelations/v1#LeaseOut">
                <meta property="price" content="0.00">
            </td>
            <td>Due: 2/5/2016
                <link property="availability" href="http://schema.org/OutOfStock">
                <meta property="availabilityStarts" href="2016-05-02">
            </td>
            <td>
              <span title="Means not available. Item is on loan
                to a customer. The person who has the item may return it by the
                date specified or keep it longer if the item can be
                renewed.">On loan</span>
            </td>
            <td>650.1 NEW</td>
          </tr>
          <tr property="offers" typeof="Offer" resource="#offer2">
            <td>
              <b><a href="http://tpl.ca/detail.jsp?Nr=p_cat_branch_name:Toronto%20Reference%20Library"
                    property="seller" typeof="Library"><span property="name">Toronto Reference Library</span></a>
              </b>
            </td>
            <td>Reference
                <link property="businessFunction" href="http://tpl.ca/using-the-library/borrowing-materials/#referenceitems">
                <meta property="price" content="0.00">
            </td>
            <td>Bus Sci & Tech 3rd Fl Reference Careers
                <link property="availability" href="http://schema.org/InStoreOnly">
            </td>
            <td>
              <span title="Means available. Item is on the
                shelf at the library branch. Note: it's always a good idea
                to call the branch to confirm that the item is there.">In
                Library</span>
            </td>
            <td>650.1 NEW</td>
          </tr>
        </tbody></table>
--- 

Provide finer grained location information

Earlier, you identified with which library each item is associated; however, that may not be enough to identify the location of a given copy of a resource. There are a number of other Offer properties that are suitable for providing more granular location information for items:

Add markup for the call number in the holdings page.

Check your markup
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf8">
  <title>Deep work : rules for focused success in a distracted world
    : Newport, Cal, author.
    : Book, Regular Print Book
    : Toronto Public Library</title>
</head>
<body vocab="http://schema.org/" typeof="Book Product" resource="#book">
  <link property="sameAs" href="http://calnewport.com/books/deep-work/">
...
<h1 property="name">Deep work : rules for focused success in a distracted world</h1>
...
      <table>
        <tbody><tr property="offers" typeof="Offer" resource="#offer1">
            <td>
              <b><a href="http://tpl.ca/detail.jsp?Nr=p_cat_branch_name:Agincourt"
                    property="seller" typeof="Library"><span property="name">Agincourt</span></a>
              </b>
            </td>
            <td>Book
                <link property="businessFunction" href="http://purl.org/goodrelations/v1#LeaseOut">
                <meta property="price" content="0.00">
            </td>
            <td>Due: 2/5/2016
                <link property="availability" href="http://schema.org/OutOfStock">
                <meta property="availabilityStarts" href="2016-05-02">
            </td>
            <td>
              <span title="Means not available. Item is on loan
                to a customer. The person who has the item may return it by the
                date specified or keep it longer if the item can be
                renewed.">On loan</span>
            </td>
            <td property="sku">650.1 NEW</td>
          </tr>
          <tr property="offers" typeof="Offer" resource="#offer2">
            <td>
              <b><a href="http://tpl.ca/detail.jsp?Nr=p_cat_branch_name:Toronto%20Reference%20Library"
                    property="seller" typeof="Library"><span property="name">Toronto Reference Library</span></a>
              </b>
            </td>
            <td>Reference
                <link property="businessFunction" href="http://tpl.ca/using-the-library/borrowing-materials/#referenceitems">
                <meta property="price" content="0.00">
            </td>
            <td property="availableAtOrFrom">Bus Sci & Tech 3rd Fl Reference Careers
                <link property="availability" href="http://schema.org/InStoreOnly">
            </td>
            <td>
              <span title="Means available. Item is on the
                shelf at the library branch. Note: it's always a good idea
                to call the branch to confirm that the item is there.">In
                Library</span>
            </td>
            <td property="sku">650.1 NEW</td>
          </tr>
        </tbody></table>
---

Checkpoint: Your original HTML page should now look like book_step1.html.

Lessons learned

In this exercise, you learned how to express library holdings using the GoodRelations agent-promise-object model, adapting commercial properties to non-commercial usage where necessary.

Next codelab: Periodicals

About the author

Dan Scott is a systems librarian at Laurentian University.

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.