In this tutorial, we will show you how to customize the WooCommerce product schema to improve the appearance of your products in Google’s merchant listings. Specifically, we will add the necessary fields to the product schema data to satisfy Google Search Console’s requirements.
Afterwards, we’ll share a complete WordPress code snippet that you can copy and paste into your functions.php file and modify to achieve the desired results.
Introduction to Schema.org and Structured Data
Before we dive into the tutorial, let’s understand what structured data is and why it’s important for SEO and Google Merchant listings. Structured data is a standardized format to provide information about a page and classify the page content. It’s a way to tell search engines what your data means, not just what it says.
Schema.org is a project developed by Google, Bing, Yahoo, and Yandex, aiming to create a structured data markup schema supported by major search engines. In the context of an eCommerce site, structured data can help search engines understand product details like price, availability, and review ratings.
This is important for SEO because structured data can help search engines index and understand your content better, which can lead to improved rankings and more informative search result listings. For Google Merchant listings, structured data is used to display detailed product information directly in search results, which can enhance visibility and click-through rates.
Step 1: Understand the Function
Before we dive into the code, let’s understand the main function we will be using:
add_filter( 'woocommerce_structured_data_product', 'customize_product_schema', 10, 2 ); function customize_product_schema( $markup, $product ) { // Function body }
This function is hooked into WooCommerce’s woocommerce_structured_data_product
filter, which allows us to modify the product schema data. The function takes two arguments: $markup
, which contains the current schema data, and $product
, which is the current product object.
Step 2: Get the Brand Attribute
First, we get the ‘brand’ attribute from the product. WooCommerce allows you to set custom attributes for your products, and in this case, we’re assuming that you have a ‘brand’ attribute set. If your brand attribute has a different name, you should replace ‘brand’ with the correct name.
$brand = $product->get_attribute( 'brand' );
Step 3: Define the Return Policy
Next, we define a static return policy. This should reflect your actual return policy. If your return policy varies by product, you will need a more dynamic way to set this data.
$return_policy = array( "@type" => "MerchantReturnPolicy", "returnPolicyText" => "Your return policy text here.", // Replace with your return policy text "applicableCountry" => "Your applicable country here.", // Replace with your applicable country "returnPolicyCategory" => "https://schema.org/MerchantReturnFiniteReturnWindow", "merchantReturnDays" => Your return days here, // Replace with your number of return days "returnMethod" => "https://schema.org/ReturnByMail", "returnFees" => "https://schema.org/FreeReturn" );
Step 4: Define the Shipping Details
We also define static shipping details. Again, if your shipping details vary by product, you will need a more dynamic way to set this data.
$shipping_details = array( "@type" => "OfferShippingDetails", "shippingDestination" => array( "@type" => "DefinedRegion", "addressCountry" => "Your shipping country here." // Replace with your shipping country ), "shippingRate" => array( "@type" => "MonetaryAmount", "value" => "Your shipping rate here.", // Replace with your shipping rate "currency" => "Your currency here." // Replace with your currency ), "deliveryTime" => array( "@type" => "ShippingDeliveryTime", "businessDays" => array( "@type" => "OpeningHoursSpecification", "dayOfWeek" => array("Monday", "Tuesday", "Wednesday", "Thursday", "Friday"), "opens" => "00:00", "closes" => "23:59" ), "transitTime" => array( "@type" => "QuantitativeValue", "minValue" => Your minimum transit time here, // Replace with your minimum transit time "maxValue" => Your maximum transit time here, // Replace with your maximum transit time "unitCode" => "DAY" ), "handlingTime" => array( "@type" => "QuantitativeValue", "minValue" => Your minimum handling time here, // Replace with your minimum handling time "maxValue" => Your maximum handling time here, // Replace with your maximum handling time "unitCode" => "DAY" ), "transitTimeLabel" => "Your transit time label here." // Replace with your transit time label ) );
Step 5: Add Brand to the Product Schema
After defining the return policy and shipping details, we add the ‘brand’ to the product schema.
$markup['brand'] = $brand;
Step 6: Add Return Policy and Shipping Details to Each Offer
Finally, we check if ‘offers’ is set in the schema data. If it is, we add the return policy and shipping details to each offer.
if ( isset( $markup['offers'] ) && is_array( $markup['offers'] ) ) { foreach ( $markup['offers'] as &$offer ) { $offer['hasMerchantReturnPolicy'] = $return_policy; $offer['shippingDetails'] = array($shipping_details); } }
Step 7: Return the Modified Schema Data
At the end of the function, we return the modified schema data.
return $markup;
Step 8: Test Your Changes
Before you apply these changes to your live site, test them on a staging site first. Use Google’s Structured Data Testing Tool to validate your schema data. You can apply these changes to your live site if there are no issues.
That’s it! You now have a custom function that modifies the WooCommerce product schema to improve your Google merchant listings.
The Complete Product Schema Code Snippet
Here’s the complete code snippet that can be copied, pasted, and modified as required. Remember, this code should be placed inside your theme’s functions.php
file.
// Schema Markup Editor add_filter('woocommerce_structured_data_product', 'customize_product_schema', 10, 2); function customize_product_schema($markup, $product) { // Get 'brand' attribute $brand = $product->get_attribute('brand'); // Define static return policy and shipping details $return_policy = array( "@type" => "MerchantReturnPolicy", "returnPolicyText" => "30-day returns on all products, excludes customised products and shipping fees.", // Replace with your return policy text "applicableCountry" => "United Kingdom", // Replace with your applicable country "returnPolicyCategory" => "https://schema.org/MerchantReturnFiniteReturnWindow", "merchantReturnDays" => 30, // Replace with your number of return days "returnMethod" => "https://schema.org/ReturnByMail", "returnFees" => "https://schema.org/FreeReturn" ); $shipping_details = array( "@type" => "OfferShippingDetails", "shippingDestination" => array( "@type" => "DefinedRegion", "addressCountry" => "United Kingdom" // Replace with your shipping country ), "shippingRate" => array( "@type" => "MonetaryAmount", "value" => "9.99", // Replace with your shipping rate "currency" => "GBP" // Replace with your currency ), "deliveryTime" => array( "@type" => "ShippingDeliveryTime", "businessDays" => array( "@type" => "OpeningHoursSpecification", "dayOfWeek" => array("Monday", "Tuesday", "Wednesday", "Thursday", "Friday"), "opens" => "00:00", "closes" => "23:59" ), "transitTime" => array( "@type" => "QuantitativeValue", "minValue" => 3, // Replace with your minimum transit time "maxValue" => 7, // Replace with your maximum transit time "unitCode" => "DAY" ), "handlingTime" => array( "@type" => "QuantitativeValue", "minValue" => 1, // Replace with your minimum handling time "maxValue" => 7, // Replace with your maximum handling time "unitCode" => "DAY" ), "transitTimeLabel" => "Days." // Replace with your transit time label ) ); // Add brand to the product schema $markup['brand'] = $brand; // Check if 'offers' is set in the schema data if (isset($markup['offers']) && is_array($markup['offers'])) { foreach ($markup['offers'] as &$offer) { $offer['hasMerchantReturnPolicy'] = $return_policy; $offer['shippingDetails'] = array($shipping_details); } } return $markup; }
To use this code, replace all the placeholder text (the comments next to each field) with your actual data. After making the necessary changes, save the functions.php
file and upload it to your server. Always remember to back up your original functions.php
file before making changes in case you need to revert.
Testing Structured Data with Google’s Testing Tool
After you’ve implemented the code snippet in your WooCommerce setup, testing the structured data is essential to ensure it’s correctly formatted and recognized by Google. You can use Google’s Structured Data Testing Tool for this purpose.
Here’s how to do it:
- Go to the Google Structured Data Testing Tool.
- Paste a product page URL from your website into the search bar.
- Click the ‘Run Test’ button. The tool will then fetch and analyze your page.
- Once the analysis is complete, you’ll see the structured data elements that Google was able to detect on your page. Look for the ‘Product’ schema and check if the fields we added are present and correctly populated.
Handling Errors and Warnings
During testing, you might encounter errors or warnings. An error usually means that a required field is missing or there’s a problem with the data format. A warning indicates that an optional field is missing. In the context of our tutorial, you should pay special attention to the fields related to the return policy and shipping details.
If you see any errors or warnings, revisit the code snippet and ensure that you’ve replaced all placeholders with your actual data. If you’re still having issues, consider reaching out to a developer or posting a question on a WooCommerce or SEO forum.
FAQ
Q: Can I use a different attribute instead of ‘brand’? Yes, you can replace ‘brand’ with any product attribute that you’ve set in your WooCommerce setup.
Q: I don’t offer free returns. How can I reflect this in the schema? You can modify the ‘returnFees’ field in the return policy array. Replace ‘https://schema.org/FreeReturn‘ with ‘https://schema.org/ReturnShippingFees‘.
Q: My shipping rates vary by product. How can I handle this? Our tutorial provides a static shipping rate for simplicity. If your shipping rates vary, you would need to dynamically fetch the shipping rate for each product and add it to the ‘shippingRate’ field.
Q: How often should I test my structured data? Testing your structured data whenever you change your website or the product schema is a good practice. Regular testing can help you catch and fix issues promptly.
By following this guide and understanding the basics of structured data, you can enhance your WooCommerce product listings on Google and provide a better shopping experience for your customers.