13 Feb A Hands-On Introduction to Modern JavaScript for SEOs via @hamletbatista
When I initially placed the React component script in the HTML HEAD, I go this error in the JavaScript Console.
When I clicked on the error line reported submit_review.js:38, I was presented with the problematic code.
I suspected the selector wasn’t working, so I set a breakpoint (green highlighted line 36) and refreshed the page. This halts the page rendering on this line and brings up the Chrome JavaScript debugger. I can click to step through the line and mouse over the variable domContainer, and it was null, which means there was no value.
I typed the selector line of code in the JavaScript Console and I got the value as expected. What was happening here?
In order to understand the issue, we need to read about the lifecycle of an HTML page.
When browser loads a page it goes through different phases and not all parts of the page are available. Everything is available when the page is fully loaded.
I am executing JavaScript code in the head that is trying to find content in the BODY, which has yet to fully load.
So, to fix this issue, I simply moved my component script to the bottom of the page. Right before the closing HTML BODY tag.
<!-- Footer --> <footer> <div> <div> <p>Copyright © Home of the best cakes, 2018 | <a href="http://html5-templates.com/" target="_blank" rel="nofollow">HTML5 Templates</a></p> </div> </div> </footer> </div> <!-- /.container --> <!-- Load our React component. --> http://submit_review.js </body></html>
Adding Structured Data to our Recipe Page
Now that we have a basic recipe page with a barely functioning button, let’s add some structured data to help make our page stand out in the SERPs.
We are going to follow the steps in this codelab.
“Since our sample site is a recipe blog, we’re going to start with recipe structured data. Recipe structured data can provide a rich result that can include rich information, like a description of your recipe, cooking and preparation times, and nutrition information. Your content may also automatically enable a recipe badge for Google Images on mobile devices, voice guidance on the Google Home, and a content action on the Google Assistant.”
Google’s preferred format for structured data is JSON-LD. This is good because it dramatically simplifies implementation.
We can add all markup in a single place on the page and avoid the complication of nesting values.
<script type="application/ld+json">{"@context": "http://schema.org/","@type": "Recipe","name": "Party Coffee Cake"}</script>
This is our work in progress implementation. We are specifying the page contains a recipe for a Party Coffee Cake. This page contains all the details we need to complete our implementation.
Please note that we need to specify the type as “application/ld+json”. By default, browsers assume “application/javascript”. We are also specifying schema.org as the markup type.
After we add the remaining required properties, we can test them in the Structured Data Testing Tool. We can see all values organized and displayed nicely.
However, we can see a warning about a missing optional attribute.
warning aggregateRating | The aggregateRating field is recommended. Please provide a value if available. |
We are going to improve the markup by adding a nested Review element.
"review": { "@type": "Review", "reviewRating": { "@type": "Rating", "ratingValue": "4", "bestRating": "5" }, "author": { "@type": "Person", "name": "Mary Stone" }, "datePublished": "2018-05-01", "reviewBody": "This cake is delicious!", "publisher": "The cake makery" }
"aggregateRating": { "@type": "AggregateRating", "ratingCount": "18", "ratingValue": "4" }
Generate JSON-LD Markup with JavaScript
It is good that we produced valid markup, but as the data is hardcoded, it won’t update the number of reviews as we add them.
Let’s put our new JavaScript skills to good use and fix this!
For illustration purposes, we will simply increase the number of reviews on the web page and the JSON-LD object when we submit a new review.
The same approach can be used to populate the JSON-LD object with data from the page. However, in practice the data for the JSON-LD object will come from a database, the same way as the content for the page is.
var json_str = `{ "@context": "http://schema.org/", "@type": "Recipe", "review": { "@type": "Review", "reviewRating": { "@type": "Rating", "ratingValue": "4", "bestRating": "5" },// Plus other elements }`;
The important technique here is that I saved the whole hard-coded JSON-LD code in a JavaScript string variable. I used backticks to handle multiple lines of text.
function update_ratingCount(ratingCount){ var jsonld = JSON.parse(json_str);jsonld.aggregateRating.ratingCount = ratingCount; return JSON.stringify(jsonld);}
I used JSON.parse to convert the string to an object that makes it easy to reference any element in the JSON-LD structure.
See how I can navigate nested levels using dots in jsonld.aggregateRating.ratingCount. Then, after I update the ratingCount value, I need to convert the object back to a string for insertion into the page.
Finally, we need to update the render() function of our React component. It should perform the following additional steps:
- Extract the current number of reviews
- Increase them by one
- Update the page with the increased reviews
- Update the JSON-LD as well, but it will replace the whole script with the one generated by the function we created.
if (this.state.submitted) { //get current reviews var review_count = document.querySelector("body > div > div:nth-child(4) > div.col-lg-12 > h2").textContent; review_count = review_count.split(" ")[0] //increase current rating count by one var count = parseInt(review_count); count++; review_count = count.toString(); //now that we have the new number of reviews. We can update the page and the JSONLD document.getElementById("user_reviews").innerHTML = `${review_count} user reviews`; document.getElementById("jsonld").innerHTML = update_ratingCount(review_count); if(this.name == ""){ return `You submitted ${this.state.review}`; }else{ return `${this.state.name}, you submitted ${this.state.review}`; } }
I tested this in Chrome and I can see the values updated under the developer tool’s element tab. It won’t work with the Structured Data Testing Tool because the changes are not permanent.
And there you have it. If you try these code snippets and the codelab yourself, you should have learned enough JavaScript to be dangerous!
Community Projects & Resources to Learn More
The best way to learn programming and JavaScript, in particular, is by practicing it. The more you do it, the better you get at it.
Don’t get discouraged by the initial obstacles, come back to them later with fresh ideas.
Here are some tutorials to get you warmed up.
- JavaScript Tutorial from W3C Schools
- The Modern JavaScript Tutorial
- CSS Selectors reference from W3C
- Getting Started with JavaScript Debugging
This year started with so much excitement around Python, coding, and automation in the SEO community.
So many cool projects, articles, videos and introduction guides.
I’m so glad that everybody is building off the work of each other and making the community stronger and more fun every day.
Here are some projects that I want to highlight.
How to Aggregate & Automate Performance Reporting With Lighthouse & Google Data Studio https://t.co/KXYH7Ndb3I /by @DanLeibson#measurepic.twitter.com/uibiGvEwQw
— Google Analytics (@googleanalytics) January 23, 2020
Dan Leibson and gang not only created an amazing Lighthouse automation tool in Nodejs. They open-sourced it and got it featured by the Google Analytics Twitter account!
🤯🤯🤯Rory just blew my mind 10X with this beautifully detailed notebook covering so many advanced concepts 👏🏻👏🏻👏🏻. He started learning #Python last year! So proud of our growing 🐍🔥SEO community! #DONTWAIThttps://t.co/yuJzEWLIJI
— Hamlet 🇩🇴 🇺🇸 (@hamletbatista) January 24, 2020
Rory Truesdale from Conductor just started learning Python last year and put together a crazily advanced notebook with so many valuable features. Very impressive!
Clustering/text mining w/ BERT. was very lucky to be exposed to very smart people/projects and putted together this experimental code, apologize ahead the code has no comments and its super beta, yet, think this can be good to share. @hamletbatista@jroakes@RoryT11@fightopic.twitter.com/wA2HdXgzQL
— Gefen Hermesh (@Ghermesh) January 24, 2020
Gefen Hermesh created a sophisticated clustering solution that leverages BERT.
@jroakes makes amazing things. https://t.co/CLk6YsmCMI
— 🍌 John 🍌 (@JohnMu) December 10, 2019
JR Oakes has been coding incredible things. A mini internet that got big praise from John Muller and more recently an advanced keyword clustering algorithm.
Hülya Çoban put together this amazing notebook that helps plot Google Trends in Google Data Studio.
This is going to be an exciting year for sure.
More Resources:
- Understanding JavaScript Fundamentals: Your Cheat Sheet
- SEO Guide to Angular: Everything You Need to Know
- Advanced Technical SEO: A Complete Guide
Image Credits
All screenshots taken by author, February 2020
Sorry, the comment form is closed at this time.