Outputting structured product attributes in JSON-LD code with SEOMatic 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, 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. Like Brand. How do I add Brand to my JSON-LD? I guess all attributes from Schema.org are supported?
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 &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) %}


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