What I understand from your question, you’ve already generated product schema via Woocommerce and you want to append/insert additional multiple ImageObject
- for ALL the images attached (added within the content/product long description/etc./no-gallery images) to the product - within generated product schema.
Before heading to the solution, these are the issues with your code:
- foreach clause is not closed
creator
object type can be Organization or Person only which both belongs to CreativeWork category. Use the object type i-e: Organization or Person, not the CreativeWork category name here since it’ll fail rich results test.
- In
contentUrl
, you are using only guid which is not an URL. guid is only a unique identifier, however, markup needs full URL to the attachment.
- Use ACTUAL context in the filter hook name i-e: product. So instead of
woocommerce_structured_data_context
use woocommerce_structured_data_product
. If you leave generic word context, it will override markup for all context like breadcrumb and others. Keep your context specifically product for product related images.
- In schema, you don't need to enforce
orderby
and order
, so clean them from get_children
arguments
- Since you want
ImageObject
markup for ALL attachments, clean out the posts_per_page
too from arguments.
Solution (Tested, Validated, & Vetted for Recommended Usage)
The solution is tested with latest (up to the date) Woocommerce, Wordpress, and also validated with Google Rich Results testing tool.
add_filter( 'woocommerce_structured_data_product', 'wc_add_product_structed_data_images', 10, 1 );
function wc_add_product_structed_data_images ( $markup ) {
$images = array(); //replaced ss with s
$images = get_children(
array( 'post_parent' => get_the_ID(), 'post_type' => 'attachment', 'post_mime_type' => 'image')
);
if(count($images) > 0) { // just ensuring we really have childrens or additional images
/** prepare image objects before insertion */
$imageObjects = array();
foreach($images as $i) {
//Prepare the single image meta data
$singleImageObject = array(
"@type" => "ImageObject",
"name" => "Name of the image",
"creator" => array(
"@type" => "Organization",
"name" => "Name of Creator"
),
"creditText" => "Creative Dept.",
"embeddedTextCaption" => "The caption of image.",
"description" => "The short description of the image.",
"contentUrl" => wp_get_attachment_url($i->ID),
"license" => "https://creativecommons.org/licenses/by-nd/2.0/",
"acquireLicensePage" => "https://creativecommons.org/licenses/by-nd/2.0/",
"copyrightNotice" => "2008 to 2022"
);
/** Pushing image to image objects */
$imageObjects[] = $singleImageObject;
}
/** Based on image property existence, lets push the objects in markup now */
if(isset($markup['image'])) { //if it is set, it returns an URL string only; not ImageObject.
$markup['image'] = array($markup['image']); //converting to array while preserving first image added by woo
$markup['image'][] = $imageObjects;
} else { //if no image property is yet set, lets set it and add ImageObject array
$markup['image'] = array();
$markup['image'][] = $imageObjects;
}
return $markup;
}
return $markup;
}
Code Explanation
- I changed the filter hook from
context
to product
and cleaned the arguments.
- Firstly: If we really have attachments, I prepared the
ImageObject
markup by looping through all images, creating an ImageObject
associate array $singleImageObject
for individual image, and then pushing/merging all of the ImageObject
into one array $imageObjects
.
- Secondly: The image property might already be set by Woo for featured image and if it sets it in string format. It means, we must either append the image property or we should override it completing by adding featured image and additional ones. In the above code, I checked if we've the image property set, I converted the data type to array (since if it set already it is string), then I pushed back the existing string URL for featured image to preserve it, and finally pushed/appended the prepared
$imageObjects
into the $markup['image']
Additional Notes
- In the ImageObject markup, you can replace image name, creator name and type (Organization or Person) only, embeddedTextCaption with image caption, and other properties to their respective dynamic or static values or as needed.
- If you're developing a theme with it and using this filter, make sure your theme uses
wp_footer()
in the footer since this filter uses wp_footer
hook to output its contents.