Answers.Body: <p>Andrew will likely come along and give a better answer, but you can definitely extend the outputted JSON-LD in SEOMatic.  No need to copy any of the schema things over, I think.</p>
  <p>Here's an example from a good while ago of adding brand, mpn, sku to the <code>mainEntityOfPage</code> i.e. your Product.</p>
  <pre><code>
  {% if not craft.app.request.isAjax and 'debug' not in craft.app.request.segment(1) %}
      
      {# Set the brand ... #}
      {% set mainEntity = seomatic.jsonLd.get('mainEntityOfPage') %}
      {% set brand = product.brand.one() ??? null %}
  
      {% if brand|length %}
          {% set productBrand = seomatic.jsonLd.create({
              'type': 'Brand',
              'name': brand.title,
              'url': brand.homepageUrl,
          }, false) %}
      {# If someone has left off the brand, let's just say it belongs to us... #}
      {% else %}
          {% set productBrand = seomatic.jsonLd.create({
              'type': 'Brand',
              'name': 'Store Brand',
              'url': 'https://yourstore.com',
          }, false) %}
      {% endif %}
  
      {% do mainEntity.brand(productBrand) %}
      {# We use the title here as the actual offers below have the real MPN/SKU #}
      {% do mainEntity.mpn(product.title) %}
      {% do mainEntity.sku(product.title) %}
  
  {% endif %}
  
  </code></pre>
  <p>Here's an example dealing with offers, for the actual variants of that product (assuming these are variant products):</p>
  <pre><code>
      {# We show out of stock offers even for discontinued products at the moment #}
      {% set offers = [] %}
      {% for variant in variations %}
  
              {% set offers = offers|merge([seomatic.jsonLd.create({
                  'type': 'Offer',
                  'name': variant.description,
                  'description': variant.description,
                  'url': product.url,
                  'availability' : (variant.available and object.available and (variant.hasUnlimitedStock or variant.stock &gt; 0)) ? 'http://schema.org/InStock' : 'http://schema.org/OutOfStock',
                  'itemCondition' : 'https://schema.org/NewCondition',
                  'mpn' : variant.mpn ??? &quot;&quot;,
                  'price' : variant.salePrice|number_format(2, '.', ''),
                  'priceCurrency' : 'AUD',
                  'priceValidUntil' : now | date_modify('+1 year') | atom,
                  'offeredBy' : {&quot;@id&quot; : &quot;https://yourstore.com/#identity&quot;},
                  'seller' : {&quot;@id&quot; : &quot;https://yourstore.com/#identity&quot;},
                  'sku': variant.sku,
                  'image' : (one(object.masterImage)|length) ?   { &quot;@type&quot;: &quot;ImageObject&quot;, &quot;url&quot; : &quot;https://yourstore.com&quot; ~ craft.imager.transformImage( one(object.masterImage), 'large' ).getUrl() } : &quot;&quot;,
                  'category' : (one(object.categories)|length) ? one(object.categories).title : &quot;&quot;,
              }, false)]) %}
  
      {% endfor %}
  
      {% do mainEntity.offers(offers) %}
  
  </code></pre>
  <p>SEOmatic is really very well documented, you'd want to review (well, the whole Using SEOMatic section really!) - but more specifically:</p>
  <p><a href="https://nystudio107.com/docs/seomatic/Using.html#seomatic-variables" rel="nofollow noreferrer">https://nystudio107.com/docs/seomatic/Using.html#seomatic-variables</a></p>
  <p>and</p>
  <p><a href="https://nystudio107.com/docs/seomatic/Using.html#json-ld-meta-object-functions-seomatic-jsonld" rel="nofollow noreferrer">https://nystudio107.com/docs/seomatic/Using.html#json-ld-meta-object-functions-seomatic-jsonld</a></p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-11-21T23:06:14.943Z
Answers.Text: Nope, that's a great answer! :)
Answers.UserDisplayName: andrew.welch
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-11-20T22:48:23.217Z
Answers.LastActivityDate: 2020-12-11T06:01:38.567Z
Answers.LastEditDate: 2020-12-11T06:01:38.567Z
Answers.UserDisplayName: Jeremy Daalder
Body: <p>My products have a lot of attributes that I would like to serve to Google AMP via JSON-LD. The attributes vary between product types.</p>
  <p>How should I do this?</p>
  <p>I see there is a file under <code>nystudio107\craft-seomatic\src\seomatic-config\productmeta\JsonLdContainer.php</code>, and I am guessing I should put that file in my own config and modify it a bit, but I am not sure how to approach this.</p>
  <p><strong>Edit: Then of course there is the question</strong>: What are you really trying to do?</p>
  <p>I am under the impression that I can tell Google what the different attributes on my product are, and that Google can use this when generating rich previews of search results. I understand that Google has a list of <a href="https://developers.google.com/search/docs/guides/search-gallery" rel="nofollow noreferrer">Supported Structured Data</a>, and from that it doesn't seem you can or should add additional non-supported attributes to the JSON-LD output...</p>
  <p>Then again, I see there are a lot of attributes that <a href="https://support.google.com/merchants/answer/6386198?hl=en" rel="nofollow noreferrer">are in fact supported</a>. Like Brand. How do I add Brand to my JSON-LD? I guess all attributes from <a href="https://schema.org/docs/full.html" rel="nofollow noreferrer">Schema.org</a> are supported?</p>
  
Tags: <plugin-seomatic>
Title: Outputting structured product attributes in JSON-LD code with SEOMatic
ThreadText: # Outputting structured product attributes in JSON-LD code with SEOMatic
  
  (Asked by: username_0 on 2020-11-20)
  
  My products have a lot of attributes that I would like to serve to Google AMP via JSON-LD. The attributes vary between product types.
  
  How should I do this?
  
  I see there is a file under `nystudio107\craft-seomatic\src\seomatic-config\productmeta\JsonLdContainer.php`, and I am guessing I should put that file in my own config and modify it a bit, but I am not sure how to approach this.
  
  **Edit: Then of course there is the question**: What are you really trying to do?
  
  I am under the impression that I can tell Google what the different attributes on my product are, and that Google can use this when generating rich previews of search results. I understand that Google has a list of [Supported Structured Data](https://developers.google.com/search/docs/guides/search-gallery), and from that it doesn't seem you can or should add additional non-supported attributes to the JSON-LD output...
  
  Then again, I see there are a lot of attributes that [are in fact supported](https://support.google.com/merchants/answer/6386198?hl=en). Like Brand. How do I add Brand to my JSON-LD? I guess all attributes from [Schema.org](https://schema.org/docs/full.html) are supported?
  
  **Tags:** plugin-seomatic
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2020-11-20. Score: 2 | Accepted answer
  
  Andrew will likely come along and give a better answer, but you can definitely extend the outputted JSON-LD in SEOMatic. No need to copy any of the schema things over, I think.
  
  Here's an example from a good while ago of adding brand, mpn, sku to the `mainEntityOfPage` i.e. your Product.
  
  ```
  
  {% if not craft.app.request.isAjax and 'debug' not in craft.app.request.segment(1) %}
      
      {# Set the brand ... #}
      {% set mainEntity = seomatic.jsonLd.get('mainEntityOfPage') %}
      {% set brand = product.brand.one() ??? null %}
  
      {% if brand|length %}
          {% set productBrand = seomatic.jsonLd.create({
              'type': 'Brand',
              'name': brand.title,
              'url': brand.homepageUrl,
          }, false) %}
      {# If someone has left off the brand, let's just say it belongs to us... #}
      {% else %}
          {% set productBrand = seomatic.jsonLd.create({
              'type': 'Brand',
              'name': 'Store Brand',
              'url': 'https://yourstore.com',
          }, false) %}
      {% endif %}
  
      {% do mainEntity.brand(productBrand) %}
      {# We use the title here as the actual offers below have the real MPN/SKU #}
      {% do mainEntity.mpn(product.title) %}
      {% do mainEntity.sku(product.title) %}
  
  {% endif %}
  
  ```
  
  Here's an example dealing with offers, for the actual variants of that product (assuming these are variant products):
  
  ```
  
      {# We show out of stock offers even for discontinued products at the moment #}
      {% set offers = [] %}
      {% for variant in variations %}
  
              {% set offers = offers|merge([seomatic.jsonLd.create({
                  'type': 'Offer',
                  'name': variant.description,
                  'description': variant.description,
                  'url': product.url,
                  'availability' : (variant.available and object.available and (variant.hasUnlimitedStock or variant.stock > 0)) ? 'http://schema.org/InStock' : 'http://schema.org/OutOfStock',
                  'itemCondition' : 'https://schema.org/NewCondition',
                  'mpn' : variant.mpn ??? "",
                  'price' : variant.salePrice|number_format(2, '.', ''),
                  'priceCurrency' : 'AUD',
                  'priceValidUntil' : now | date_modify('+1 year') | atom,
                  'offeredBy' : {"@id" : "https://yourstore.com/#identity"},
                  'seller' : {"@id" : "https://yourstore.com/#identity"},
                  'sku': variant.sku,
                  'image' : (one(object.masterImage)|length) ?   { "@type": "ImageObject", "url" : "https://yourstore.com" ~ craft.imager.transformImage( one(object.masterImage), 'large' ).getUrl() } : "",
                  'category' : (one(object.categories)|length) ? one(object.categories).title : "",
              }, false)]) %}
  
      {% endfor %}
  
      {% do mainEntity.offers(offers) %}
  
  ```
  
  SEOmatic is really very well documented, you'd want to review (well, the whole Using SEOMatic section really!) - but more specifically:
  
  <https://nystudio107.com/docs/seomatic/Using.html#seomatic-variables>
  
  and
  
  <https://nystudio107.com/docs/seomatic/Using.html#json-ld-meta-object-functions-seomatic-jsonld>
  
  > **Comments:**
  > **username_2**: Nope, that's a great answer! :)  
  
  ---
  
  