Opencart extensions free download · 9 min read · Updated

Product Structured Data (JSON-LD) in OpenCart 4: Get Rich Results for Price, Stock and Reviews (Free Extension)

Add schema.org Product, Offer, Review, BreadcrumbList and Organization JSON-LD to OpenCart 4.1 for Google rich results and AI shopping agents. Field mapping, testing steps and a free extension.

Opencart 4 product structured data json ld

Search results that show the price, “In stock” and a star rating under a product get more clicks than plain blue links. Those extras come from structured data: a small block of JSON-LD in the page that tells search engines exactly what the product is, what it costs and whether it is available.

The same data is now read by AI shopping assistants. As we explained in Making an OpenCart Store Agent-Ready, an agent comparing products trusts structured facts far more than a pretty description.

The default OpenCart 4 theme outputs no structured data at all. This post shows which schema types a store needs, how OpenCart 4.1’s fields map to them, and gives you a free extension that adds it all without editing theme files.

Which schema types an online store needs

PageSchema typeWhat it can give you
Product pageProduct + OfferPrice, availability and shipping in Google results and in the Shopping tab
Product pageAggregateRating + ReviewStar rating and review count
Product pageMerchantReturnPolicy, OfferShippingDetails“Free returns”, delivery time and shipping cost in results
Product and category pagesBreadcrumbListA readable path (Home › Laptops › MacBook) instead of the URL
Home pageOrganization + WebSiteYour logo and social profiles in the knowledge panel

Google decides when to show rich results; correct markup makes you eligible, it doesn’t guarantee them. But wrong or missing markup guarantees you won’t get them.

What the output looks like

This is what the extension adds to a product page on the OpenCart demo data (shortened):

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Product",
  "@id": "https://yourstore.com/en-gb/product/macbook#product",
  "name": "MacBook",
  "description": "Intel Core 2 Duo processor. Powered by an Intel Core 2 Duo processor at speeds up to 2.16GHz...",
  "url": "https://yourstore.com/en-gb/product/macbook",
  "image": [
    "https://yourstore.com/image/cache/catalog/demo/macbook_1-500x500.jpg",
    "https://yourstore.com/image/cache/catalog/demo/macbook_2-500x500.jpg"
  ],
  "sku": "MB-2024",
  "mpn": "MC207LL/A",
  "gtin": "0885909302387",
  "brand": { "@type": "Brand", "name": "Apple" },
  "category": "Laptops & Notebooks",
  "offers": {
    "@type": "Offer",
    "url": "https://yourstore.com/en-gb/product/macbook",
    "priceCurrency": "USD",
    "price": "602.00",
    "priceValidUntil": "2026-12-31",
    "availability": "https://schema.org/InStock",
    "itemCondition": "https://schema.org/NewCondition",
    "seller": { "@type": "Organization", "name": "Your Store" },
    "hasMerchantReturnPolicy": {
      "@type": "MerchantReturnPolicy",
      "applicableCountry": "US",
      "returnPolicyCategory": "https://schema.org/MerchantReturnFiniteReturnWindow",
      "merchantReturnDays": 30,
      "returnMethod": "https://schema.org/ReturnByMail",
      "returnFees": "https://schema.org/FreeReturn"
    },
    "shippingDetails": { "@type": "OfferShippingDetails", "...": "..." }
  },
  "aggregateRating": {
    "@type": "AggregateRating",
    "ratingValue": "4.5",
    "reviewCount": 12,
    "bestRating": 5,
    "worstRating": 1
  },
  "review": [
    {
      "@type": "Review",
      "author": { "@type": "Person", "name": "Sam" },
      "datePublished": "2026-09-14",
      "reviewBody": "Fast and quiet, battery lasts all day.",
      "reviewRating": { "@type": "Rating", "ratingValue": 5, "bestRating": 5 }
    }
  ]
}
</script>

How OpenCart 4.1 fields map to schema.org

This is the part most tutorials get wrong for OpenCart 4.1, because two things changed from OpenCart 3:

  • Product codes moved. The product form no longer has separate SKU, UPC, EAN, JAN, ISBN and MPN fields. Codes are saved as rows in oc_product_code, and the code types are defined in oc_identifier (Catalog > Identifiers in the admin), where you can add your own, like GTIN-14. The old columns still exist on oc_product, and stores upgraded from OpenCart 3 may still have data there, so the extension reads oc_product_code first and falls back to the old columns.
  • Specials moved. Special prices are stored in oc_product_discount with special = 1 instead of a separate oc_product_special table.
schema.org propertyOpenCart 4.1 sourceNotes
name, descriptionProduct name and description (current language)HTML tags stripped, description cut to 5,000 characters
imageMain image + additional imagesFull URLs, up to 5 images
skuIdentifier SKU, falls back to model
mpnIdentifier MPN
gtinIdentifier EAN, UPC, JAN or ISBN (you choose the order)Only numeric values of 8, 12, 13 or 14 digits are used
brandManufacturerOmitted if no manufacturer is set
offers.priceSpecial, then discount, then price, with tax if your store shows prices with taxSame price the customer sees on the page, in the session currency
offers.priceValidUntilEnd date of the active specialOmitted if there is no end date
offers.availabilityQuantity > 0 = InStock, otherwise the product’s Out Of Stock StatusYou map each stock status (2-3 Days, Pre-Order…) to a schema value
aggregateRatingAverage and count of approved reviewsCalculated with one decimal; OpenCart’s own rating is rounded to a whole number
reviewLatest approved reviewsNumber is configurable, default 5

If your products have no GTIN, MPN or brand, that is allowed. Google only asks for them when they exist. But for branded products, adding them under Catalog > Products > Edit > Data tab > Product Codes is the single best improvement you can make for Google Shopping.

How the extension adds the markup

The extension uses OpenCart 4 events, so it works with any theme and survives OpenCart updates:

Event triggerAdds
catalog/view/product/product/afterProduct (+ Offer, rating, reviews, return and shipping policy) and BreadcrumbList
catalog/view/product/category/afterBreadcrumbList
catalog/view/common/home/afterOrganization and WebSite (with site search)

Each handler builds a PHP array, encodes it with json_encode(), and inserts the <script type="application/ld+json"> block just before </head>. Using json_encode() rather than writing JSON in a Twig template matters: product names with quotes, ampersands or line breaks can’t break the JSON, and </script> inside a description can’t escape the block.

A simplified version of the product handler:

// catalog/view/product/product/after
public function product(string &$route, array &$data, string &$output): void {
    if (!$this->config->get('module_product_schema_status') || empty($data['product_id'])) {
        return;
    }

    $this->load->model('extension/product_schema/module/product_schema');

    // $data is what the product page sends to its template, so breadcrumbs and
    // manufacturer are already there.
    $schema = $this->model_extension_product_schema_module_product_schema->getProductSchema(
        (int)$data['product_id'],
        $data['breadcrumbs'],
        $data['manufacturer']
    );

    if ($schema) {
        $json = json_encode($schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_TAG);

        $script = '<script type="application/ld+json">' . $json . '</script>' . "\n";

        $position = stripos($output, '</head>');

        if ($position !== false) {
            $output = substr_replace($output, $script, $position, 0);
        }
    }
}

JSON_HEX_TAG turns < and > into < and >, which is what keeps a stray </script> harmless. If you are new to events, our OpenCart 4 OCMOD tutorial compares them with OCMOD.

Installation

  1. Download product_schema.ocmod.zip.
  2. Go to Extensions > Installer, upload the zip and click Install.
  3. Go to Extensions > Extensions > Modules, find Product Structured Data (JSON-LD), click + to install, then the pencil to edit.
  4. Configure the settings below, set Status to Enabled and click Save.

Settings

General

  • Status – on or off.
  • Markup to output – switch each of Product, BreadcrumbList, Organization and WebSite on or off. Turn off any type your theme already outputs (see "Duplicate markup" below).
  • Reviews to include – 0 to 10. 0 keeps the star rating but leaves out individual reviews.
  • Item condition – New, Used or Refurbished, for the whole store.
  • GTIN identifiers – which identifier codes to use as GTIN, in order of preference (default EAN, UPC, JAN, ISBN).

Availability mapping

Each stock status from Localisation > Stock Statuses is listed with a dropdown of schema.org values: InStock, OutOfStock, PreOrder, BackOrder, LimitedAvailability, SoldOut, Discontinued. The defaults match OpenCart's demo statuses: "In Stock" → InStock, "2-3 Days" → BackOrder, "Pre-Order" → PreOrder, "Out Of Stock" → OutOfStock.

Returns and shipping

Google shows returns and delivery information from MerchantReturnPolicy and OfferShippingDetails. Fill these in only if they are true for most of your products:

  • Return policy: country (two-letter code), return window in days (0 = no returns), free or customer-paid returns.
  • Shipping: destination country, flat shipping rate (0 for free shipping), handling time and transit time in days (minimum and maximum).

If you also use Google Merchant Center, the return and shipping settings there take priority, and they should match what you put here.

Organization

The organization name, logo, email and phone come from System > Settings. Add your social profile URLs (one per line) to fill sameAs, which helps Google connect your site to your Facebook, Instagram, X or YouTube pages.

Test your markup

  1. Open Google's Rich Results Test and enter a product URL. You should see Product snippets and Merchant listings as valid items, plus Breadcrumbs.
  2. Fix any red errors. Yellow warnings such as "Missing field gtin" are optional, but fill them in where you can.
  3. Use the Schema Markup Validator for a full view of everything on the page, including markup your theme adds.
  4. After a few days, check Google Search Console > Enhancements (Product snippets, Merchant listings, Breadcrumbs) for errors across the whole site.

For a quick check without a browser:

curl -s https://yourstore.com/en-gb/product/macbook | grep -o '<script type="application/ld+json">.*</script>'

Common mistakes

  • Duplicate markup. Some premium themes add their own Product schema or microdata. Two Product blocks with different prices confuse Google. Check with the Schema Markup Validator and either turn off the theme's markup or turn off that type in the extension.
  • Price doesn't match the page. Google compares the markup price with the visible price and with your Merchant Center feed. The extension uses the same price calculation as the product page, including specials and tax, so keep your theme's price display standard.
  • Fake or imported reviews. Only real customer reviews may be marked up. Reviews written by the store, or copied from other sites, break Google's guidelines and can lead to a manual action. The extension only uses reviews you approved under Catalog > Reviews.
  • Markup on a page Google can't index. Structured data does nothing on a page blocked by robots.txt or set to noindex. See 25 SEO best practices for OpenCart and make sure product URLs are in your sitemap.
  • Products with options. If size or colour options change the price, the markup shows the base price, which is the price shown on the page before an option is chosen. Full ProductGroup variant markup needs separate URLs per variant, which OpenCart doesn't have by default.

Google AI Overviews, ChatGPT shopping, Perplexity and other AI assistants read the same JSON-LD. A product with a clear price, availability, brand, GTIN and return policy is easier for them to recommend correctly than one they have to guess from HTML. Structured data works alongside the other pieces we have covered: how AI crawlers read your website, llms.txt for ecommerce and content for generative search.

Summary

  1. The default OpenCart 4 theme has no structured data. Install the extension, or add JSON-LD with events as shown above.
  2. Fill in brand (manufacturer) and GTIN/MPN under the product's identifiers wherever you have them.
  3. Map your stock statuses to schema availability values and add your return and shipping policy.
  4. Test with the Rich Results Test, remove duplicate theme markup, and monitor Search Console.

Find more free OpenCart extensions, or contact us if you need help with structured data on a custom theme.

Rupak Nepali
Written byRupak Nepali

Author of four Opencart book.
The recent are Opencart 4 developer book and Opencart 4 user manual

Leave a Reply

Your email address will not be published. Required fields are marked *