Monday, December 22, 2014

Microdata Christmas Cookies

When writing my previous post on transforming a Wikibook textbook, I discovered the Cookbook.  I use an iPad app called Paprika to collect recipes from the web but the Wikibook pages did not import very well. Unfortunately I discovered that the recipes do not include microdata.  In the holiday spirit of sharing cookies, let’s share some recipes. 

To share recipes (or other structured content) with Google, Bing, and Yahoo, microdata adds robot-friendly SEO goodness. Cooking sites like All Recipes, Epicurious, etc. include microdata which gives app designers a predictable data format.  

Here is a taste of what you can do with Edge80 and the MediaWiki publisher to create your own sharable cookbook collection. If you are just getting started, have a look at the High School Earth Science post. I may skip over some of the details found there in this post to avoid too much repetition. 


Original Wikibook Category and Recipe
~~
Visit the original Wikibook
New Custom Home Page and Recipe
~~
Visit the adapted cookbook




What we did:

  • Converted to Zurb Foundation 5 Responsive Layout
  • Added a new custom home page
  • Inserted microdata attributes 
  • Added Disqus comments
  • Customised some specific pages 
  • CSS styling


Converted to Zurb Foundation 5 Responsive Layout


Again, the Edge80 MediaWiki solution does most of the work. I picked the Foundation theme this time. My new project folder included a set of files under my existing account. (You can set one up a new account as part of the process if you don’t have one.) 

At this point I had a project I re-named WikiBook-Recipes that contained all my files, and the Domains tab showed me the URL where I could view the site under my sandbox runs80.com domain.



Added a New Custom Home Page


The recipes I wanted to gather were already a Wikibook Category - great for an index, but not very exciting for a book cover. I created a new home page and modified the navigation to include links to my home page and an index page (the original category list).  

In my top-level rules.xml file, there is a comment showing you where to make edits to specific files. I added a rule to fetch my hand rolled home.html file that I uploaded into my project.  

<rule match-path="*/Cookiebook" comment="Custom Home Page">
    <apply name="lib.content_tags"/>
    <compose buffer="meta">
        <literal>
            <title>A Merry Microdata Cookie Cookbook - by Edge80</title>
            <meta name="description" content="Everyone Loves A Cookie" />   
        </literal> 
    </compose>
    <compose>  
        <fetch type="resource" url="static/home.html"/>
    </compose>              
</rule>


Inserted Microdata Attributes 


Most of the recipes were consistent in layout, but had no microdata.  I referred to schema.org for allowable recipe attributes and proceeded to modify them in my rules.xml file.

In the rule named user.page_edits I cleaned up some layout and display issues, then started to add itemscope, itemtype and itemprop attrubutes. 

<rule name="user.page_edits">
<!-- Tweaks after the whole page is constructed. -->
    <compose priority="4000">
            
        <modify xpath="//body">
            <attribute action="set" name="itemscope" />
            <attribute action="set" name="itemtype"
                value="http://schema.org/Recipe" />
        </modify>
        <modify xpath="//*[@id='title-row']/div/h1">
            <attribute action="set" name="itemprop" value="name" />
        </modify>
               
        <modify xpath="//table[@class='infobox']/tr/th[contains(text(),'Category')]/../td" >
            <attribute action="set" name="itemprop" value="recipieCategory" />
        </modify>    
        <modify xpath="//table[@class='infobox']/tr/th[contains(text(),'Servings')]/../td" > 
            <attribute action="set" name="itemprop" value="recipieYield" />
        </modify>
        <wrap xpath="//*[@id='Ingredients']/../following-sibling::ul[1]"
            placeholder-tagname="wrapped">
            <div class='ing-div'><wrapped></wrapped></div>
        </wrap>
        <modify xpath="//*[@class='ing-div']/ul/li">
            <attribute action="set" name="itemprop" value="ingredients" />
        </modify>
        <replace xpath="//*[@class='ing-div']/ul/li/a" with="contents" />

        ...
    </compose>
</rule>

(I'm sure there is probably a way to identify the elements to modify using js, but I used xpath. Every cook has favorite tools. )

One thing I did was wrap the list of cookie dough ingredients in a containing div I named ing-div.  This helped with my css layout and floats. It also made it easier to add the ingredients itemprop attribute. 

Another decision was to remove links from the ingredients items.  The original pages include links to pages for measurements and topics like sugar, vanilla and salt.  (An arbitrary decision, but felt it may confuse the microdata demonstration.) Notice that Edge80 has a nifty way to remove the surrounding tags from some linked text. 

    <replace xpath="//*[@class='ing-div']/ul/li/a" with="contents" />


Added Disqus Comments


You can also add third party widgets to some or all of your site pages. I created a rule for any recipe that had ‘Chocolate’ in its name, add a Disqus comment form.  I grabbed the Disqus-provided script code for my account and added it with this rule:

<rule match-path-re="Chocolate">
    <apply name="framework.proxy_edited" />        
    <compose priority="3300">
        <insert xpath="//*[@id='catlinks']" action="after" with="literal">
            <div id="disqus_thread"></div>
            <script type="text/javascript">
                var disqus_shortname = 'MY_DISQUS_ACCOUNT_NAME'; 
                    (function() {
                        var dsq = document.createElement('script'); 
                        dsq.type = 'text/javascript'; dsq.async = true;

                        ...
            </script>
        </insert> 
    </compose>        
</rule>
  

Customised Some Specific Pages 


One problem I had with some of the original content was occasionally a page would actually have 2 versions of a recipe, like Snickerdoodles and Peanut Butter Cookies

For accurate structured content, there really should only be one. The content remains useful for human cookie bakers, but the benefit of adding the microdata is probably a bit lost. Although it would be possible to remove one of the recipes with a simple rule, I did not for this example.  

CSS Changes for Responsive Displays


I used very standard css style changes for colors and fonts to keep the content readable and device-friendly.  Use your own preferences and spice to your tastes. 



Food For Thought


Recipes are just one of the information types that are ideal for microdata formatting.  You can see how easy it is to add or replace standard attributes for data types using the MediaWiki Publisher and Edge80 modifications. The Schema.org blog is releasing a new version in early 2015 that will include tags for sports, breadcrumbs and more. 
  • Microdata will increase your SEO rankings
  • You can re-purpose legacy web content for structured data interoperability (e.g. in JSON)
  • Microdata is essential for ecommerce sites and the advent of 'searchandising'. 
Oh, and just like the textbook project: 
  • MediaWiki can be used as a robust content management system backend
  • Edit links, talk pages and history can be removed from your public site
  • No need for an m-dot site for mobile, which can hurt SEO
  • Modify, tailor and style content for public-only viewing

Have some fun and find a cookie recipe to make and share with friends, pets or friendly robots over the holiday season.