In a previous exercise, you marked up holdings in a catalog page with the schema.org vocabulary using RDFa attributes. However, when you identified the library that holds a given copy of a resource, you only used a text string--and as there are many library branches named "Main Branch" or "Central Library" in the world, general consumers of your structured data such as search engines may not be able to determine basic information such as where your library is located, and fail to connect potential patrons with your library's resources. In this exercise, you will mark up library web pages with address information, contact information, and opening hours, then link your catalog pages to the library web pages to complete the relationship between your resources and your library.
When you search for a library on different search engines, you will probably get different and conflicting sets of information about the library. The results often depend on where the information is pulled from, which in turn depends on relationships that the search engines have with various data providers. For example, comparing searching for my home library J.N. Desmarais Library:
This is a sad state of affairs, and while our library certainly could work harder on outreach and search engine optimization, we are hardly alone.
Having to maintain information such as address, contact information, and hours of operation in multiple places is inefficient and error-prone. Rather than pushing information to multiple sites, it makes much more sense to allow interested sites to pull the information from one authoritative source. OCLC has positioned themselves to provide this information to the various commercial companies, but the simplest possible method would be for libraries to simply mark up their own library home pages (where that information almost certainly already exists for the benefit of human readers) with the relevant schema.org structured data so that the machines can benefit as well.
Audience: Intermediate
Prerequisites: To complete this codelab, you should already be familiar with HTML, RDFa, and schema.org. The previous exercise offers a practical introduction to those concepts.
Library
entity
The core information that many users want to find when they look for a
business online include locations, operating hours, contact
information, and branch relationships. For libraries, schema.org models
this information in the Organization
-> LocalBusiness
-> Library
hierarchy.
In this exercise, you will take a simple library web page and
identify some of the core information in it using the
Library
type and its properties.
Open step1/centennial_branch.html
in a text editor. You should see something like the following HTML source for
the web page:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>LVCCLD-Centennial Hills Library</title></head>
<body>
<div id="main-content">
...
<div id="main-copy">
<!-- #main-copy-->
<p id="breadcrumb"><a href="../index.cfm">Home</a> / <a href="locations.cfm">Locations & Hours</a></p>
<h2>Centennial Hills Library</h2>
<div class="photo"><img src="../images/library.png" width="180" height="165" alt="Centennial Hills Library Photo"></div>
<div style="float:left; margin:0 0 0 15px;">
<div style="font-weight:bold">
Address:
</div>Centennial Hills Library<br>
6711 N. Buffalo Dr.<br>
Las Vegas, NV 89131<br>
<div style="font-weight:bold">
Hours:
</div>M - Th, 10 a.m. - 8 p.m.<br>
F - Sun, 10 a.m. - 6 p.m.
</div>
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).
Library
Edit the <body>
element to include your @vocab
declaration for the schema.org vocabulary, add a @typeof
value of
Library
, and set a
@resource
value. Check the results with one or more of the
structured data testing tools.
You should see that the page is now recognized as describing a
Library
entity.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>LVCCLD-Centennial Hills Library</title>
</head>
<body vocab="http://schema.org/" typeof="Library" resource="#library">
<div id="main-content">
...
name
, image
, and description
properties
As most schema.org types inherit from Thing
, some of the core
properties are name
,
image
, and description
.
These properties are often used to generate rich snippets (short
summaries displayed in search results).
Declare the appropriate name
, image
, and
description
properties for this library.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>LVCCLD-Centennial Hills Library</title>
</head>
<body vocab="http://schema.org/" typeof="Library" resource="#library">
<div id="main-content">
...
<h2 property="name">Centennial Hills Library</h2>
<div class="photo">
<img src="../images/library.png" alt="Centennial Hills Library Photo" property="image">
</div>
...
<div style="font-weight:bold">
About the Library:
</div>
<div property="description">
<p>Opened in 2009, the 45,555 SF Centennial
Hills Library is located at the intersection of N. Buffalo Drive and Deer
Springs Way, adjacent to the Centennial Hills Park. The building is
LEED certified gold, meaning it is constructed to reduce negative environmental
impacts and improve occupant health and well-being.
</p>
<p>The library offers:</p>
<ul>
<li>A well-rounded collection of books, magazines, newspapers, DVDs, music CDs and audio books</li>
<li>A 22-seat Adult Computer Lab, 12 family resource computers, 8 children's computers, free Wi-Fi, and wireless printing</li>
<li>A dedicated Homework Help Center that includes 20 laptops</li>
<li>Weekly storytimes and special programs for a wide variety of ages</li>
<li>One meeting room with a 60-seat capacity</li>
<li>A used bookstore and café area</li>
<li>Knowledgeable, friendly staff to assist you</li>
</ul>
</div>
</div><!-- /#main-copy-->
...
Identifying the address for the branch helps consuming applications provide
a geographic context for their users. For example, the application could
order search results based on proximity to the searcher's own geolocation.
The Organization
type from which Library
inherits includes a address
property for this
purpose. address
expects a PostalAddress
entity for its value, which includes the following properties:
addressCountry
addressLocality
addressRegion
postOfficeBoxNumber
postalCode
streetAddress
Mark up the address for this branch.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>LVCCLD-Centennial Hills Library</title>
</head>
<body vocab="http://schema.org/" typeof="Library" resource="#library">
...
<div style="font-weight:bold">
Address:
</div>
<div property="address" typeof="PostalAddress">
Centennial Hills Library<br>
<span property="streetAddress">6711 N. Buffalo Dr.</span><br>
<span property="addressLocality">Las Vegas</span>,
<span property="addressRegion">NV</span> <span property="postalCode">89131</span>
</div>
...
Operating hours are one of the most frequently consulted pieces of
information for any organization. The schema.org vocabulary provides
two different ways of marking up operating hours. In this exercise,
you will use the much more structured openingHoursSpecification
(which was derived from the GoodRelations vocabulary)
instead of the similarly named but less structured openingHours
.
The openingHoursSpecification
property expects a OpeningHoursSpecification
type, which is composed of the following properties:
closes
hh:mm:ss[Z|(+|-)hh:mm]
format.dayOfWeek
Day | Value |
---|---|
Monday | http://purl.org/goodrelations/v1#Monday |
Tuesday | http://purl.org/goodrelations/v1#Tuesday |
Wednesday | http://purl.org/goodrelations/v1#Wednesday |
Thursday | http://purl.org/goodrelations/v1#Thursday |
Friday | http://purl.org/goodrelations/v1#Friday |
Saturday | http://purl.org/goodrelations/v1#Saturday |
Sunday | http://purl.org/goodrelations/v1#Sunday |
Public holidays | http://purl.org/goodrelations/v1#PublicHolidays |
opens
hh:mm:ss[Z|(+|-)hh:mm]
format.validFrom
validThrough
Given this information, mark up the operating hours for this branch.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>LVCCLD-Centennial Hills Library</title>
</head>
<body vocab="http://schema.org/" typeof="Library" resource="#library">
...
<div style="font-weight:bold">
Hours:
</div>
<div property="openingHoursSpecification" typeof="OpeningHoursSpecification">M - Th,
<link property="dayOfWeek" href="http://purl.org/goodrelations/v1#Monday">
<link property="dayOfWeek" href="http://purl.org/goodrelations/v1#Tuesday">
<link property="dayOfWeek" href="http://purl.org/goodrelations/v1#Wednesday">
<link property="dayOfWeek" href="http://purl.org/goodrelations/v1#Thursday">
<span property="opens" content="10:00:00">10 a.m.</span> -
<span property="closes" content="20:00:00">8 p.m.</span>
</div>
<div property="openingHoursSpecification" typeof="OpeningHoursSpecification">F - Sun,
<link property="dayOfWeek" href="http://purl.org/goodrelations/v1#Friday">
<link property="dayOfWeek" href="http://purl.org/goodrelations/v1#Saturday">
<link property="dayOfWeek" href="http://purl.org/goodrelations/v1#Sunday">
<span property="opens" content="10:00:00">10 a.m.</span> -
<span property="closes" content="18:00:00">6 p.m.</span>
</div>
...
Library patrons frequently want to find an email address or telephone
number to contact their library. The
contactPoint
property from Organization
expects a
ContactPoint
type, which bundles together contact properties such as
email
and
telephone
.
Use a ContactPoint
entity to define the telephone
property for your branch. Note: although it is not required by
schema.org, providing a machine-readable telephone number via a
content
attribute is recommended by
Google and therefore probably a good idea.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>LVCCLD-Centennial Hills Library</title>
</head>
<body vocab="http://schema.org/" typeof="Library" resource="#library">
...
<div class="contact" property="contactPoint" typeof="ContactPoint">
<div style="font-weight:bold">
Phone:
</div>
<meta property="contactType" content="customer service">
<span property="telephone" content="+17025076100">(702) 507-6100</span><br>
<div style="font-weight:bold">
Branch manager:
</div>Tamara Gieseking<br>
<br>
<a href="http://maps.google.com/maps?f=q&hl=en&geocode=&q=6711+N.+Buffalo+Dr.+Las+Vegas+NV+89131&sll=36.285173,-115.258427&sspn=0.057217,0.096989&ll=&ie=UTF8&z=14&iwloc=addr" target="_blank" style="text-decoration:none; float:left">
<span style="width:66px; height:64px; background:url(../images/compass.png) no-repeat top left; padding:0 10px 0 0; float:left"></span><span style="float:left; line-height:64px;">View Map</span>
</a>
</div>
...
Checkpoint: Your original HTML library branch page should now look like step1/branch_check_a.html.
In this exercise, you learned how to express locations, operating hours, and contact information for a library branch.
When you marked up holdings in your catalog page in the previous exercise,
you simply used the name of the library as the value of the
seller
property. However, the seller
property
expects an Organization
, not a text value. Now that you
have marked up your library branch web page as a Library
entity, you can link your holdings directly to the entity in your
library branch web page. This provides much more contextual information
about that holding (such as location, hours of operation, and contact
information) to consumers of your linked data.
Edit step1/rdfa_book.html to link the
"Centennial Hills YPL" holdings to the Library
entity in your
library branch web page.
<!DOCTYPE html>
<html>
<head>
<title>Las Vegas-Clark County Library District /All Locations</title>
</head>
<body vocab="http://schema.org/" typeof="Book Product" resource="#book">
...
<tr class="bibItemsEntry" property="offers" typeof="Offer">
<td><link property="seller" href="branch_check_a.html#library">Centennial Hills YPL</td>
<td property="sku"><a href="/search~S12?/hJ/hj/-3,-1,,B/browse">J</a></td>
<td>ON HOLDSHELF
<link property="availability" href="http://schema.org/OutOfStock">
<link property="businessFunction" href="http://purl.org/goodrelations/v1#LeaseOut">
<meta property="price" content="0.00">
</td>
</tr>
<tr class="bibItemsEntry" property="offers" typeof="Offer">
<td><link property="seller" href="branch_check_a.html#library">Centennial Hills YPL</td>
<td property="sku"><a href="/search~S12?/hJ/hj/-3,-1,,B/browse">J</a></td>
<td>ON HOLDSHELF
<link property="availability" href="http://schema.org/OutOfStock">
<link property="businessFunction" href="http://purl.org/goodrelations/v1#LeaseOut">
<meta property="price" content="0.00">
</td>
</tr>
<tr class="bibItemsEntry" property="offers" typeof="Offer">
<td><link property="seller" href="branch_check_a.html#library">Centennial Hills YPL</td>
<td property="sku"><a href="/search~S12?/hJ/hj/-3,-1,,B/browse">J</a></td>
<td property="availabilityStarts" content="2014-06-10T00:00:00">DUE 06-10-14
<link property="availability" href="http://schema.org/OutOfStock">
<link property="businessFunction" href="http://purl.org/goodrelations/v1#LeaseOut">
<meta property="price" content="0.00">
</td>
</tr>
...
Checkpoint: Your catalog page should now look like step1/book_check_a.html.
Next codelab: Periodicals
Dan Scott is a systems librarian at Laurentian University.
This work
is licensed under a Creative
Commons Attribution-ShareAlike 4.0 International License.