NewThe tragent CLI is on npm: npx @tragent/cli scan your-store.com

Issue reference

Your product data does not say what delivery costs

Issue code
SCHEMA_OFFER_SHIPPING_MISSING
Stage
Read the details
Protocol
—
Severity
Low

What it means

tragent reports this at the “Read the details” stage. The question there is “Can it understand what the product is?” Name, description, images and variants have to be readable as data, not just rendered as a page.

What it does to an agent

Agents get through, but your store reads less clearly to them than it could. It is worth fixing once the higher-severity issues are gone.

A shopper asks for the delivered price, and an agent can only answer it if the shipping cost and delivery time are in the data. Without them it quotes the item price, the shopper sees shipping added at checkout, and the comparison it made was wrong.

You can declare shipping on each Offer, or once for the whole store on your Organization, which Google also accepts. The store-wide form is usually less work.

How to fix it

Add Offer.shippingDetails (rate and delivery time), or one hasShippingService on your Organization.

OfferShippingDetails
"shippingDetails": {
  "@type": "OfferShippingDetails",
  "shippingRate": { "@type": "MonetaryAmount", "value": "4.95", "currency": "USD" },
  "shippingDestination": { "@type": "DefinedRegion", "addressCountry": "US" },
  "deliveryTime": {
    "@type": "ShippingDeliveryTime",
    "handlingTime": { "@type": "QuantitativeValue", "minValue": 0, "maxValue": 1, "unitCode": "DAY" },
    "transitTime": { "@type": "QuantitativeValue", "minValue": 2, "maxValue": 5, "unitCode": "DAY" }
  }
}

On your platform

Shopify

The structured_data filter does not include shipping. Add it per offer in a custom block, or add an Organization block to theme.liquid with your shipping service, so it applies to every product.

WooCommerce

WooCommerce does not add shipping to the markup. Add shippingDetails to each offer with the structured data filter, from your flat rate.

PHP
// In your child theme's functions.php, or a small plugin.
add_filter( 'woocommerce_structured_data_product', function ( $markup, $product ) {
    if ( isset( $markup['offers'][0] ) ) {
        $markup['offers'][0]['shippingDetails'] = array(
            '@type'               => 'OfferShippingDetails',
            'shippingRate'        => array( '@type' => 'MonetaryAmount', 'value' => '4.95', 'currency' => get_woocommerce_currency() ),
            'shippingDestination' => array( '@type' => 'DefinedRegion', 'addressCountry' => 'US' ),
        );
    }
    return $markup;
}, 10, 2 );

Headless or custom

Generate the rate from the same table checkout uses, per destination you ship to.

In practice

Model what checkout charges. If shipping is free above a threshold, declare the rate that applies below it and let the agent compare; if you ship to several countries at different rates, declare one shippingDetails per destination. Delivery time is two parts, handling and transit, and agents add them up to answer "will it arrive by Friday", so give both.

Keep the data in step with checkout. A rate in the markup that is lower than checkout charges is the same problem as a wrong price: the agent quotes it and the shopper finds out at the last step. If your rates change often, generate the markup from your shipping configuration rather than writing numbers into a template.

If you offer several speeds, such as standard and express, declare each as its own shippingDetails with its rate and delivery time. Agents answering "cheapest" and agents answering "fastest" pick different ones, and a store that declares only standard shipping loses the shopper who needed it tomorrow, even though you could have delivered.

Check the fix

  1. Check the JSON-LD for shippingDetails on an offer, or hasShippingService on the Organization.
  2. Run the scan; the shipping finding should be gone.

Run the check that reported SCHEMA_OFFER_SHIPPING_MISSING again after the change. The scan needs no account; an issue found during an AI shopping test needs that test run again.

Terminal
npx @tragent/cli scan https://your-store.com

Common mistakes

  • Declaring free shipping in the data when it applies only over a threshold.
  • A rate for one country with no destination, which reads as worldwide.