16

I'm developing a website and I want to add structured data to detailed pages. The problem is that I need to request the data before knowing what to add to the JSON-LD script.

I am using Parse as a backend. I also tried to look around for tutorials on how to achieve that but it seems not possible to add JSON-LD dynamically.

I really hope someone can help me with that! :)

EDIT:

The response with the data I need to put in the JSON-LD comes after the DOM is ready. What is it the pattern in this situations?

I have a list of items and when clicking on one of them I have to open a detail page which I have to load first, but after content is loaded I want to provide structured data through JSON-LD.

I'm at the beginning and I'm finding hard times solving this.

EDIT 2:

This is my actual implementation:

In the HTML:

<body>
    // my html page code
    ...
    <script type="text/javascript">
        loadDetailPageContent();
    </script>
</body>

In the JS:

function loadDetailPageContent() {
    // Calling the method here is too early because I don't have info
    //writeData();
    createDetailPage();
}

function createDetailPage() {
    var recipe = Parse.Object.extend("Recipe");
    var query = new Parse.Query(recipe);
    query.equalTo("objectId", myId);
    query.first({
        success: function(result) {
            // Calling the method here would be perfect
            writeData();
        },
        error: function(error) {
            alert("Error: " + error.code + " " + error.message);
        }
    });
}

function writeData() {
    var script = document.createElement('script');
    script.type = 'application/ld+json';
    script.text = JSON.stringify({
        "@context": "http://schema.org",
        "@type": "Recipe",
        "name": "My recipe name"
    });
    document.querySelector('head').appendChild(el);
}

As you can see the method writeData() is called in two places. If I call it immediately at the beginning, there is no problem and with the use of the Google Structured Data testing tool, I am able to track the structured data I need. The problem with that is that at that point I don't have the information to create the structured data because I need to wait for the response from Parse.

When I am calling the method in the success callback, then the testing tool is not able to retrieve the data anymore :(

Jamie Bohanna
  • 417
  • 1
  • 3
  • 19
AlexBalo
  • 1,220
  • 1
  • 11
  • 16
  • You can create a script that creates the JSON-LD dynamically, google's structured data parser - http://stackoverflow.com/questions/27169085/javascript-inside-ld-json – Mousey Aug 01 '15 at 18:11
  • Hey Mousey, thank you, I found the answer you linked, the problem is that I need to wait for a response from a request before creating the JSON-LD. If I add the code in the aswer in a js file, the structured data is not there – AlexBalo Aug 01 '15 at 18:16
  • you just need to use either `window.onload` or `$(document).ready()` to wait for the DOM to be ready, put the part creating the JSON-LD inside that http://stackoverflow.com/questions/799981/document-ready-equivalent-without-jquery – Mousey Aug 01 '15 at 18:19
  • Oh! Thanks Mousey I will try that and give you a feedback!! – AlexBalo Aug 01 '15 at 18:24
  • Thank you Mousey but even by following your suggestion I was not able to achieve the result :( – AlexBalo Aug 02 '15 at 07:43
  • can you post your code, and what the loaded document DOM shows? – Mousey Aug 02 '15 at 10:32
  • Hi @Mousey, I added the code snippet I have in my implementation. Hope it clarifies my issue a bit more :) – AlexBalo Aug 02 '15 at 16:10
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/84941/discussion-between-alexbalo-and-mousey). – AlexBalo Aug 02 '15 at 16:14
  • 1
    @AlexBalo did you get the perfect answer?. I required some help if you short out this issue with json-ld created with ajax response. I can not see results updated on google. Not event in google structured tool. – Parth Trivedi Oct 28 '17 at 05:56

2 Answers2

23

http://jsfiddle.net/c725wcn9/2/embedded

You will need to inspect the DOM to check this works. Jquery is needed.

$(document).ready(function(){
   var el = document.createElement('script');
   el.type = 'application/ld+json';
   el.text = JSON.stringify({ "@context": "http://schema.org",  "@type": "Recipe", "name": "My recipe name" });

   document.querySelector('head').appendChild(el);
});

Your code included the variable name script but appended the variable el to the <head> instead. Also removed are the new line characters from the JSON string which was checked with JSON-LD playground .

Mousey
  • 1,793
  • 15
  • 34
  • 1
    Oh, ok, great Mousey, I will check this answer tonight when at home. For the el variable I probably just copied and pasted incorrectly. I will give you a feedback soon. – AlexBalo Aug 04 '15 at 10:09
  • Hi Mousey, I tried with your code but unfortunately Google Tool for testing strucured data is not able to find my injected json. https://developers.google.com/structured-data/testing-tool/. I think the problem is due to the fact that I need to wait for the response of my Parse request before injecting and at that point the page has been already scanned for structured data. I really have problems understanding how it works. – AlexBalo Aug 04 '15 at 19:50
  • @AlexBalo - that's why you need to inspect the DOM to get the dynamically created JSON-LD code ,you can then copy it into the google tester, or create a test page with the code and crawl it then see if it comes up (took 2 days for mine). Google's tool does not check dynamic code and neither does the structured data linter tool. – Mousey Aug 04 '15 at 20:36
  • Yeah, I checked the DOM and the content is added. But this JSON-LD is always different and I cannot copy it into the page. The question is how can I make my dinamic page having this code if everytime it changes? – AlexBalo Aug 04 '15 at 20:44
  • Your original question was how to created JSON-LD dynamically after the DOM loads. This script does that because it run after the document `ready`jquery command. Just add your extra code into the new script right before calling `Stringify` and use variables as part of the content. The JSON-LD will be understood by search engines despite the tool only being available for testing static structured data. An easy check is to set the modified data in the JSON-LD to the (calculated) document's modified date with a variable. – Mousey Aug 04 '15 at 20:56
  • 1
    Ah ok so you mean that with Google tool it will not be retrieved but if I see it in the DOM it means that search engines will be able to understand it, right? I can check it in approx. 2 days for example in my search console, correct? – AlexBalo Aug 04 '15 at 21:06
  • 1
    Thank you Mousey for the help! – AlexBalo Aug 04 '15 at 21:08
  • @AlexBalo, may I ask you if your approach worked in Google Search Console? I am deciding which structured data format to use (JSON-LD, Microdata or RDFa) and info from you would help me (and possibly others too) a lot. – Michal Moravcik Jan 23 '17 at 19:04
  • Hi all, yes the method worked for me. I had then to move away from Parse since they shutted down and I changed the code in the website. But I remember that it was working fine. – AlexBalo Jan 23 '18 at 14:07
  • how's this right answer? this code doesn't reflect in the page source and will only be visible inside the developer's tools... – popeye Apr 02 '18 at 08:38
0

i think Mousey perfectly answered this, i am going to share similar scenario where we load flight details on page but for price we call an API when page load, so we have to load schema dynamically when we get price.

We created a nested function which we call on page load and pass flight details then on page load when we call "priceGraber" API (to get flight price), Once priceGraber return successful response then we inject schema on page.

Schema Creator Function:

    // create product schema
createProductSchema = function(from, to, currency) {
    return injectSchema = function(price) {
        let el = document.createElement('script');
        el.type = 'application/ld+json';
        el.text = JSON.stringify({
            "@context": "https://schema.org/",
            "@type": "Product",
            "name": `Flight from ${from} to ${to}`,
            "description": `Cheap flights from ${from} to ${to}`,
            "offers": {
                "@type": "Offer",
                "url": `http://flightsearches.net?fso=${from}&fsd=${to}`,
                "priceCurrency": `${currency}`,
                "availability": "https://schema.org/InStock",
                "price": `${price}`,
            }
        });

        console.log('inject now ');
        document.querySelector('head').appendChild(el);
    };
};

On Page Load Pass Information for schema which is available on page load

below script is inside blade file, {{ $flight_from }}, {{ $flight_to }} are blade directive (server side variables)

        <script>
    $(function(){
                if(typeof createProductSchema == "function") {
                    console.log('create product schema...');
                    window.injectProductSchema = createProductSchema({{ $flight_from }},  {{ $flight_to }});
                } else {
                    console.error("product schema creator doesn't exists !");
                }
            });

         </script>

Dynamically Injecting Schema

we call below function inside ajax response where we get "price" form API and then this function call nested function which then append schema into head

window.injectProductSchema(price); 
Furqan Freed
  • 301
  • 3
  • 6