Announcement

Collapse
No announcement yet.

ReadyTheme Rich Snippets Code Deprecated

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    #16
    If you're going to update your site you may as well switch to Google's preferred method of structured data, JSON-LD, instead of the micro-data. It's faster spider-food and easier to maintain.

    I like the JSON-LD @type parameter because it provides a better method to graph a website and organization, instead of individual webpages.

    http://www.alphabetsigns.com/

    Comment


      #17
      Here is a starting point for the JSON-LD code. Both Shadows and Colossus ship with this as a JavaScript Resource which you can enable in the administration portal.
      Code:
      <mvt:comment><!-- Google Tag Manager - Data Layer --></mvt:comment>
      var dataLayer = dataLayer || [];
      <mvt:comment><!-- Page Type Assignment --></mvt:comment>
      <mvt:if expr="l.settings:page:code EQ 'SFNT'">
          <mvt:assign name="l.settings:dataLayer:pageType" value="'home'" />
      <mvt:elseif expr="l.settings:page:code EQ 'SRCH' OR l.settings:page:code EQ 'SEARCH'">
          <mvt:assign name="l.settings:dataLayer:pageType" value="'searchresults'" />
      <mvt:elseif expr="l.settings:page:code EQ 'CTGY'">
          <mvt:assign name="l.settings:dataLayer:pageType" value="'category'" />
      <mvt:elseif expr="l.settings:page:code EQ 'PROD'">
          <mvt:assign name="l.settings:dataLayer:pageType" value="'product'" />
      <mvt:elseif expr="l.settings:page:code CIN 'BASK,ORDL,OCST,OUS1,OUSM,OSEL,OPAY'">
          <mvt:assign name="l.settings:dataLayer:pageType" value="'cart'" />
      <mvt:elseif expr="l.settings:page:code EQ 'INVC'">
          <mvt:assign name="l.settings:dataLayer:pageType" value="'purchase'" />
      <mvt:else>
          <mvt:assign name="l.settings:dataLayer:pageType" value="'other'" />
      </mvt:if>
      
      <mvt:comment><!-- Checkout Step Assignment --></mvt:comment>
      <mvt:if expr="l.settings:page:code EQ 'BASK'">
          <mvt:assign name="l.settings:datalayer:checkout_step" value="1"/>
      <mvt:elseif expr="l.settings:page:code EQ 'ORDL'">
          <mvt:assign name="l.settings:datalayer:checkout_step" value="2"/>
      <mvt:elseif expr="l.settings:page:code EQ 'OCST'">
          <mvt:assign name="l.settings:datalayer:checkout_step" value="3"/>
      <mvt:elseif expr="g.Screen EQ 'OUSL'">
          <mvt:assign name="l.settings:datalayer:checkout_step" value="4"/>
      <mvt:elseif expr="l.settings:page:code EQ 'OSEL'">
          <mvt:assign name="l.settings:datalayer:checkout_step" value="5"/>
      <mvt:elseif expr="l.settings:page:code EQ 'OPAY'">
          <mvt:assign name="l.settings:datalayer:checkout_step" value="6"/>
      </mvt:if>
      
      <mvt:comment><!-- User Email Assignment --></mvt:comment>
      <mvt:if expr="g.customer:bill_email">
          <mvt:assign name="l.settings:datalayer:userEmail" value="g.customer:bill_email" />
      <mvt:elseif expr="g.basket:bill_email">
          <mvt:assign name="l.settings:datalayer:userEmail" value="g.basket:bill_email" />
      <mvt:else>
          <mvt:assign name="l.settings:datalayer:userEmail" value="''" />
      </mvt:if>
      
      <mvt:comment><!-- Basic DataLayer Push --></mvt:comment>
      dataLayer.push({
          <mvt:if expr="g.Screen EQ 'NTFD'">
              "canonicalUri": "<mvt:eval expr="encodejavascriptstring( s.request_uri )" />",
              "event": "NTFD",
          <mvt:elseif expr="g.Screen EQ 'SRCH'">
              "canonicalUri": "<mvt:eval expr="encodejavascriptstring( s.request_uri )" />",
              "searchTerm": "&mvtj:global:Search;",
              "event": "SRCH",
          <mvt:else>
              "canonicalUri": "&mvtj:ga_tracking:url_override_unencoded;",
          </mvt:if>
          "requestUri": "<mvt:eval expr="encodejavascriptstring( s.request_uri )" />",
          "refererUri": "<mvt:eval expr="encodejavascriptstring( s.http_referer )" />",
          "pageCode": "&mvtj:page:code;",
          "pageType": "&mvtj:datalayer:pageType;",
          "pageName": "&mvtj:datalayer:pageName;",
          "userId": "&mvtj:global:basket:cust_id;",
          "userEmail": "&mvtj:datalayer:userEmail;",
          "basketId": "&mvtj:global:basket:basket_id;",
          "categoryCode": "&mvtj:global:Category_Code;",
          "categoryName": "&mvtj:datalayer:categoryName;",
          "productCode": "&mvtj:product:code;",
          "checkoutStep": "&mvtj:datalayer:checkout_step;"
      });
      
      <mvt:comment><!-- PROD DataLayer Push --></mvt:comment>
      <mvt:if expr="l.settings:page:code EQ 'PROD'">
          <mvt:if expr="NOT ISNULL l.settings:product:variant">
              dataLayer.push({
                  "ecommerce": {
                      "detail": {
                          "products": [{
                              "name": "&mvtj:product:variant:name;",
                              "id": "&mvtj:product:variant:code;",
                              "price": "&mvtj:product:variant:price;",
                              "sku": "&mvtj:product:variant:code;",
                              "category": "",
                              "variant": ""
                          }]
                      }
                  },
                  "content_type": "product",
                  "content_ids": "&mvtj:product:variant:code;",
                  "value": "&mvt:product:variant:price;",
                  "currency": "USD"
              });
          <mvt:else>
              dataLayer.push({
                  "ecommerce": {
                      "detail": {
                          "products": [{
                              "name": "&mvtj:product:name;",
                              "id": "&mvtj:product:code;",
                              "price": "&mvtj:product:price;",
                              "sku": "&mvtj:item:sku;",
                              "category": "",
                              "variant": ""
                          }]
                      }
                  },
                  "content_type": "product",
                  "content_ids": "&mvtj:product:code;",
                  "value": "&mvt:product:price;",
                  "currency": "USD"
              });
          </mvt:if>
      </mvt:if>
      
      <mvt:comment><!-- INVC DataLayer Push --></mvt:comment>
      <mvt:if expr="l.settings:page:code EQ 'INVC'">
          <mvt:foreach iterator="charge" array="order:charges">
              <mvt:if expr="l.settings:charge:type EQ 'TAX'">
                  <mvt:assign name="l.settings:gtm:tax" value="l.settings:charge:disp_amt" />
              <mvt:elseif expr="l.settings:charge:type EQ 'SHIPPING'">
                  <mvt:assign name="l.settings:gtm:shipping" value="l.settings:charge:disp_amt" />
              </mvt:if>
          </mvt:foreach>
          <mvt:if expr="miva_array_elements(l.settings:order:items) GT 1">
              <mvt:assign name="l.settings:content_ids" value="'['" />
          </mvt:if>
          <mvt:foreach iterator="item" array="order:items">
              <mvt:if expr="POS1 GT 1">
                  <mvt:assign name="l.settings:content_ids" value="l.settings:content_ids $ ',' $ asciichar(39) $ encodejavascriptstring( l.settings:item:code ) $ asciichar(39)" />
              <mvt:else>
                  <mvt:assign name="l.settings:content_ids" value="l.settings:content_ids $ asciichar(39) $ encodejavascriptstring( l.settings:item:code ) $ asciichar(39)" />
              </mvt:if>
          </mvt:foreach>
          <mvt:if expr="miva_array_elements(l.settings:order:items) GT 1">
              <mvt:assign name="l.settings:content_ids" value="l.settings:content_ids $ ']'" />
          </mvt:if>
      
          dataLayer.push({
              "event": "invc",
              "ecommerce": {
                  "purchase": {
                      "actionField": {
                          "id": "&mvtj:order:id;",
                          "revenue": "&mvtj:order:total;",
                          "tax": "&mvtj:gtm:tax;",
                          "shipping": "&mvtj:gtm:shipping;"
                      },
                      "products": [
                      <mvt:foreach iterator="item" array="order:groups">
                          <mvt:if expr="POS1 GT 1">,</mvt:if>
                          {
                              "name": "&mvtj:item:name;",
                              "id": "&mvtj:item:code;",
                              "price": "&mvtj:item:price;",
                              "sku": "&mvtj:item:sku;",
                              <mvt:if expr="miva_array_elements(l.settings:item:options) GT 0">
                                  <mvt:assign name="l.settings:item:gtm_variant" value="''" />
                                  <mvt:foreach iterator="option" array="item:options">
                                      <mvt:if expr="POS2 GT 1">
                                          <mvt:assign name="l.settings:item:gtm_variant" value="l.settings:item:gtm_variant $ ' ' " />
                                      </mvt:if>
                                      <mvt:assign name="l.settings:item:gtm_variant" value="l.settings:item:gtm_variant $ l.settings:option:opt_code" />
                                  </mvt:foreach>
                                  <mvt:if expr="l.settings:item:gtm_variant">
                                  "variant": "&mvtj:item:gtm_variant;",
                                  </mvt:if>
                              </mvt:if>
                              "quantity": &mvtj:item:quantity;
                          },
                      </mvt:foreach>
                      ],
                      "coupons": [
                      <mvt:foreach iterator="coupon" array="order:coupons">
                          "&mvtj:coupon:code;",
                      </mvt:foreach>
                      ]
                  }
              },
              "order_id": "&mvtj:order:id;",
              "order_total": "&mvtj:order:total;",
              "content_type": "product",
              "content_ids": "&mvtj:content_ids;",
              "value": &mvtj:order:total;,
              "currency": "USD"
          });
      
      <mvt:comment><!-- (OTHER)CHECKOUT PAGES DataLayer Push --></mvt:comment>
      <mvt:elseif expr="l.settings:datalayer:checkout_step">
      
          <mvt:if expr="miva_array_elements(l.settings:basket:items) GT 1">
              <mvt:assign name="l.settings:content_ids" value="'['" />
          </mvt:if>
          <mvt:foreach iterator="item" array="basket:items">
              <mvt:if expr="POS1 GT 1">
                  <mvt:assign name="l.settings:content_ids" value="l.settings:content_ids $ ',' $ asciichar(39) $ encodejavascriptstring( l.settings:item:code ) $ asciichar(39)" />
              <mvt:else>
                  <mvt:assign name="l.settings:content_ids" value="l.settings:content_ids $ asciichar(39) $ encodejavascriptstring( l.settings:item:code ) $ asciichar(39)" />
              </mvt:if>
          </mvt:foreach>
          <mvt:if expr="miva_array_elements(l.settings:basket:items) GT 1">
              <mvt:assign name="l.settings:content_ids" value="l.settings:content_ids $ ']'" />
          </mvt:if>
          dataLayer.push({
              "event": "checkout",
              "ecommerce": {
                  "checkout": {
                      "actionField": {
                          "step": &mvt:datalayer:checkout_step;
                      },
                      "products": [
                          <mvt:foreach iterator="item" array="global_minibasket:items">
                              {
                                  "name": "&mvtj:item:name;",
                                  "id": "&mvtj:item:product:code;",
                                  "price": "&mvtj:item:price;",
                                  "sku": "&mvtj:item:sku;",
                                  "category": "",
                                  "variant": "",
                                  "quantity": &mvtj:item:quantity;
                              },
                          </mvt:foreach>
                      ],
                      "coupons": [
                      <mvt:foreach iterator="coupon" array="global_minibasket:coupons">
                          "&mvtj:coupon:code;",
                      </mvt:foreach>
                      ]
                  }
              },
              "content_type": "product",
              "content_ids": "&mvt:content_ids;",
              "value": "&mvt:basket:total;",
              "currency": "USD"
          });
      </mvt:if>
      Matt Zimmermann
      Holistic Web Developer
      https://www.dev4web.net


      Site Development - Maintenance - Consultation

      Comment


        #18
        Here is a starting point for the JSON-LD code. Both Shadows and Colossus ship with this as a JavaScript Resource which you can enable in the administration portal.
        I think a note on this should be that this using Google TAG Manager (GTM) markup and not Google Analytics, meaning you'll have to create and use a GTM account to use this code.
        Bruce Golub
        Phosphor Media - "Your Success is our Business"

        Improve Your Customer Service | Get MORE Customers | Edit CSS/Javascript/HTML Easily | Make Your Site Faster | Get Indexed by Google | Free Modules | Follow Us on Facebook
        phosphormedia.com

        Comment


          #19
          Miva is a product with many features included. When the included features don't work out of the box (or off the lot) the consumer should not be told that they now will have to pay extra to get non functional standard features that come with the product to work as expected.

          It seems every time we have a problem (not this schema problem) with an embedded feature in Levels that does not work we are advised to get a developer to fix it - and these are things that are built into Levels... try to use them and they don't work out of the box - that means to me that they never worked. Fixing them is not a feature enhancement request or a "Dream Feature". Some things just don't work out of the box. I consider those to be bugs - not some enhancement request.

          This schema problem did work out of the box but it is not going to work in March for any ReadyTheme store that is using the feature.

          I had another message that in the Miva App Store only Collosus and Shadows are non legacy. Everything else is legacy (allegedly) so any features included in those ReadyThemes that don't work out of the box Miva Support will not fix (I'm guessing). At least that is what we are experiencing. That is a shame that the Miva App Store is offering so many ReadyThemes that when there is a problem the customer is going to be told to pay a developer to fix the nonworking feature.

          There has been no customization of the Rich Snippets in these stores - we just want what appears to be boilerplate that comes with the ReadyTheme to function without Google warnings or errors. The code seems to be exactly the same in the examples from the Miva App Store. It probably should just be a copy/paste (with an update/correction) of what comes with the ReadyTheme. I know I can add more if I want to but right now I don't want to. I want what came with Miva to work.

          The example link that was provided before plugs into the PROD page and updates without a Miva error but it will not pass the Google Structured Data Testing tool with an error - not a warning. That tells me that nobody tested the proposed solution or if they did test it they did not care about the errors. Maybe nobody but me cares about Google errors/warning about malformed or erroneous code. It could be that no other Miva user is looking at the Google email reports about warnings and errors.

          How can nobody else on the planet have seen these warning/errors about the built in schema code and come up with a fix to the basic schema code that comes with a ReadyTheme that can be shared? (all ReadyThemes in the Miva App Store with the schema code seem afflicted in exactly the same way).

          The Live Demos of Collosus and Shadows do not seem to include Rich Snippets (like the others do) but in March all those other ReadyThemes are going to start generating Google errors (currently warnings) so hopefully Miva will take responsibility with a copy/paste update or somebody will step up to the plate and come up with the solution.

          I have thought of some other ideas which I will be pursuing or will just stay tuned until March when every legacy ReadyTheme on the planet begins generating Google errors on every product page in every store. Somebody will come up with and hopefully share a solution.

          Comment


            #20
            As you mentioned, the microdata code for the Legacy ReadyThemes was fairly boilerplate. That being said, you should be able to take the code from Booc and, with some massaging, put it into Levels. Booc, Storyteller, and Luxe all have Schema code, although they may need updating.
            Matt Zimmermann
            Holistic Web Developer
            https://www.dev4web.net


            Site Development - Maintenance - Consultation

            Comment


              #21
              Great post! Thank you for sharing this!

              Question: In switching to GTM, should we then remove the old micro-code rich snippets, or can they be left?

              I did switch things when first working on the site from data-vocabulary.org to schema.org (for once, I chose wisely).

              Comment


                #22
                From what I can see, there is nothing wrong with leaving both on the site as other search engines will still pick up the microdata.
                Matt Zimmermann
                Holistic Web Developer
                https://www.dev4web.net


                Site Development - Maintenance - Consultation

                Comment


                  #23
                  Best answer I've heard all day! Thanks!

                  Comment


                    #24
                    I think there is some confusion with the snippet provided as a starting point for structured data.

                    The GTM DataLayer code snippet provided has nothing to do with Structured Data JSON LD.

                    That snippet is for building a DataLayer for Google Analytics Ecommerce tracking code, not Structured Data LD.

                    http://www.alphabetsigns.com/

                    Comment


                      #25
                      Oh shoot, you're correct. Looks like I had my notes mislabeled, sorry about that. I do not currently have the snipped for JSON-LD ready to go, I should have it together in the next few weeks as it will be part of the next release of Shadows.
                      Matt Zimmermann
                      Holistic Web Developer
                      https://www.dev4web.net


                      Site Development - Maintenance - Consultation

                      Comment


                        #26
                        Slightly different question but related to GTM, this snippet should not be included in the GTM bucket and must reside on the page because there is SMT?

                        And then following up that question, that rendered page with the rendered values needs to be "ajax'd" to render new values when there are other potential values.

                        And the more complex question/conclusion, likely better to keep these "dynamic rendering scripts" out of GTM? Seems like there would be potential timing issues if part of the script were in GTM bucket and the balance is in the page template?

                        Scott
                        What help do you need today!
                        Interactive Design Solutions http://www.southbound.com
                        MivaMerchant Business Partner | Certified MivaMerchant Web Developer
                        My T-shirt Collection is mostly MivaCon T-shirts!!
                        Competitive Rates, Popular Modules, and Integrations:
                        Product Copy | AutoBaskets | Waitlist Integration| Wholesale Integration

                        Comment


                          #27
                          Hey Scott, I think you had a question like this before and you got it figured out.

                          There are two different elements on the page as it relates to GTM: the dataLayer object and the app script.

                          Matt's snippet creates a JSON object named dataLayer. The script then pushes data into that object.

                          The other element on the page as it relates to GTM is the app script which reads the dataLayer object and sends it to a Google endpoint.

                          The app script is called a container that you built in Tag Manager, saved it to a container, then published the container. The container can contain many third party scripts that read the dataLayer.

                          The only GTM script that a developer needs to write to the webpage is the GTM loader script which calls and writes the latest published container script.
                          http://www.alphabetsigns.com/

                          Comment


                            #28
                            Yes, the real premise of my question was to find out if I was just lucky. JS adds complexity and I am less familiar with it. Finding out the Enhanced eCommerce stuff really won't run in GTM because of the dynamic characteristics and being SMT is an important concept to know ahead of time.

                            Scott

                            What help do you need today!
                            Interactive Design Solutions http://www.southbound.com
                            MivaMerchant Business Partner | Certified MivaMerchant Web Developer
                            My T-shirt Collection is mostly MivaCon T-shirts!!
                            Competitive Rates, Popular Modules, and Integrations:
                            Product Copy | AutoBaskets | Waitlist Integration| Wholesale Integration

                            Comment


                              #29
                              Wow, these all sound like they need some great how-to written for them.
                              Leslie Kirk
                              Miva Certified Developer
                              Miva Merchant Specialist since 1997
                              Previously of Webs Your Way
                              (aka Leslie Nord leslienord)

                              Email me: [email protected]
                              www.lesliekirk.com

                              Follow me: Twitter | Facebook | FourSquare | Pinterest | Flickr

                              Comment


                                #30
                                For the "If we had more time file...."

                                What would really be best is a miva based tool that would go through a series of questions about your site, like "what type of products you sell", "do you have reviews", "do you have variants or attributes", "to which are prices assigned", etc and then have it spit out a correct template for the micro data with the miva based variables populated. There would still be some manual coding involved (for example, what are the review variables), but you could probably get 80-85% of the way there.

                                I've seen some existing versions of this, but you have to populate the template with your own variables.

                                This does however, show why Miva can't just drop in micro data (I mean, it could, but it wouldn't be optimal).

                                Bruce Golub
                                Phosphor Media - "Your Success is our Business"

                                Improve Your Customer Service | Get MORE Customers | Edit CSS/Javascript/HTML Easily | Make Your Site Faster | Get Indexed by Google | Free Modules | Follow Us on Facebook
                                phosphormedia.com

                                Comment

                                Working...
                                X