Reading JSON+LD Structured Data with JavaScript
I'd been working on a website that included a couple of event schedule
pages for about 18 months, and so in order to take advantage of Google and Bing's enhanced snippets
display of JSON+LD data for such pages I started adding Structured Data in that format to
the site. But it felt like I was short-changing visitors to the site by not making that
data easily accessible, so I decided to write some JavaScript to locate and parse the JSON+LD data
and insert it into a toggled DIV.
Since I had no idea how to begin, I tried searching for some example JavaScript
just to get me started and found almost no help for beginners. Every article I found seemed to be
aimed at advanced users with vast experience in Structured Data and most of it was focused on
server-side solutions. Once I got a foothold on reading JSON with JavaScript, I found it was
dirt simple since JavaScript's built-in JSON object library does the dirty work for you.
My little JavaScript JSON parser scans your document for div
tags with a class name of "rdEvent", which includes a well-structured JSON data component
for each event.
Let's start with the HTML and the JavaScript JSON+LD structured data
that displays a sample event listing:
<div class="rdEvent">
<a class="eName" href="http://www.raintaxi.com/twin-cities-book-festival/">Twin Cities Book Festival</a>:
<span class="eDate">October 17</span><br>
Premier literary event in the Twin Cities held each year on the Minnesota State Fairgrounds.
This year's Festival is open from 10AM to 5PM. Free admission!
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "Event",
"name": "Twin Cities Book Festival",
"startDate" : "2015-10-17T10:00",
"endDate" : "2015-10-17T17:00",
"url" : "http://www.raintaxi.com/twin-cities-book-festival/",
"location" : {
"@type" : "Place",
"sameAs" : "http://www.mnstatefair.org/",
"name" : "Minnesota State Fairgrounds",
"address" : "1265 Snelling Avenue N, St. Paul, MN 55108"
}
}
</script>
</div>
This example JSON parser scans a document for all containing elements (like a
div) with a class name of "rdEvent". Each such
container is then scanned for a JavaScript/JSON block, whose "innerHTML" is then
parsed as a JSON Object with "JSON.parse()" and its individual properties can subsequently
be easily retrieved by JavaScript using "jsonObjectName.propertyName".
My implementation converts the location data into an address suitable
for display and adds a link labeled "Location Info" to the displayed information
block. When the link is clicked by a user, a hidden block containing the name and street
address of the location is made visible along with a link to a pop-up Google map of the
location. Try it yourself, below:
Twin Cities Book Festival:
October 17
Premier literary event in the Twin Cities held each year on the Minnesota State Fairgrounds.
This year's Festival is open from 10AM to 5PM. Free admission!
The box below contains my JavaScript JSON parser as it is used
on this page. You'll undoubtedly need to modify it for your own uses. Again, the key point is
to note how the various properties of the JSON object I named 'json' are referenced. Everything else
is specific to this example implementation. This example includes a good example of inserting
HTML code into the DOM with JavaScript that uses the JSON data to build enhanced content for the user. By
relying on JavaScript to create these additional elements, it insures that users running with JavaScript
disabled will not encounter non-functioning links and buttons.
// JSON Parser Globals
var rdEvents = new Array();
var rdJSONContainerName = 'rdEvent';
var rdLocInfoLinkText = 'Location Info';
var rdMapLinkText = 'See Map';
function rdInitShowEvent() {
var s, data, json, atag, t, spantag, locText;
rdEvents = document.getElementsByClassName(rdJSONContainerName);
for (i=0; i<rdEvents.length; i++) {
atag = document.createElement('A');
atag.setAttribute('onclick', 'return rdToggleLoc("rdLocBoxID' + i + '")');
atag.setAttribute('class', 'rdToggleBtn');
atag.setAttribute('style', 'padding:2px 4px; font-weight:bold; background-color:gold;');
t = document.createTextNode(rdLocInfoLinkText);
atag.appendChild(t);
rdEvents[i].appendChild(atag);
t = document.createElement('BR');
rdEvents[i].appendChild(t);
spantag = document.createElement('DIV');
spantag.setAttribute('class', 'rdLocBox');
spantag.setAttribute('id', 'rdLocBoxID' + i);
spantag.setAttribute('style', 'display:none;');
s = rdEvents[i].getElementsByTagName('script')[0];
data = s.innerHTML;
json = JSON.parse(data);
atag = document.createElement('A');
atag.setAttribute('href', json.location.sameAs);
atag.setAttribute('style','font-weight:bold;');
t = document.createTextNode(json.location.name);
atag.appendChild(t);
spantag.appendChild(atag);
atag = document.createElement('BR');
spantag.appendChild(atag);
t = document.createTextNode(json.location.address);
spantag.appendChild(t);
var rdLocation = json.location.address.split(',');
if (rdLocation.length == 3) {
atag = document.createElement('BR');
spantag.appendChild(atag);
var stateZip = rdLocation[2].replace(/^\s+/,'').split(' ');
link = "popZoomMap('" + rdLocation[0] + "','" + rdLocation[1] + "','" +
stateZip[0] + "','" + stateZip[1] + "','" + json.location.name + "');";
t = document.createTextNode(' ');
spantag.appendChild(t);
atag = document.createElement('A');
atag.setAttribute('onclick',link);
atag.setAttribute('class','mapButton');
atag.setAttribute('style','font-weight:bold;');
t = document.createTextNode(rdMapLinkText);
atag.appendChild(t);
spantag.appendChild(atag);
} // endif rdLocation.length
rdEvents[i].appendChild(spantag);
} // end for i
} // end rdInitShowEvent()
// Show/Hide function
function rdToggleLoc(id) {
var box = document.getElementById(id);
(box.style.display == 'none') ? box.style.display = 'block' : box.style.display = 'none';
return false;
} // end rdToggleLoc()
// Install 'onload' event to initialize the JSON Parser
if (window.addEventListener) {
window.addEventListener('load', rdInitShowEvent, false);
} else if (window.attachEvent) {
window.attachEvent('onload', rdInitShowEvent);
}
This page was last modified on August 27, 2020