首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >产品页不公开价格、只收询价,Product 结构化数据该怎么写才不误导搜索和 AI

产品页不公开价格、只收询价,Product 结构化数据该怎么写才不误导搜索和 AI

原创
作者头像
用户10345225
发布于 2026-11-03 12:41:50
发布于 2026-11-03 12:41:50
1270
举报

一个很常见的现场:页面正文写着「价格按配置与数量报价,请提交询价」,源码里却是主题示例没删干净的 "price": "0.00"。搜索结果里出现 ¥0 的商品卡片,或者 AI 摘要把「起价 0 元」直接念出来。

这类错误不报错、不崩站,只在有人看的时候丢人。下面是一套从判断页型到上线验证的流程。

先分清这是哪种页

  • 有公开价、能直接下单:标准 Product + Offer,price、priceCurrency、availability、priceValidUntil 都要跟库存和结算对得上。
  • 没有公开价、只能按配置和数量报价:本文的场景。核心决定是不写 offers。
  • 不是单个产品,而是一条产品线或一项服务:用 Service 或 CollectionPage / ItemList 描述。硬套 Product 会让搜索引擎期待一个它拿不到的价格。

没有价格就不要写 offers

Offer.price 的语义是「这个价格能买到」。填 0 表示免费,不表示面议。占位写法("price": "0"、"price": "1"、只写 priceCurrency 不写 price)要么被当成真实价格读出去,要么直接被判为无效。

这里有个代价要接受:商品富媒体结果一般要求页面有 name,再加上 offers 或真实评价中的至少一项。一个既没有公开价格、也没有真实评价的产品页,通常拿不到带价格的展示卡片。为了拿到卡片去编价格、编评分,属于明确违反结构化数据政策的做法,被人工处理比没有卡片糟得多。

同时不要:

  • 给没有评价的产品写 aggregateRating
  • availability 填 InStock,实际要报价后才知道能不能排产
  • 把询价表单页当成 offers.url,让人以为点进去就能买
  • priceValidUntil 写一个已经过去的日期

Product 里真正值得写的字段

没有价格可写,就把「这是什么」写扎实。这些字段搜索引擎会读,AI 摘要也更容易引到具体参数:

  • name、description,描述里带上「价格按配置与数量报价」这句事实
  • image,多张,绝对地址
  • brand、category、material
  • sku / mpn / gtin,只在系统里真实存在时写,不要为了「更完整」编一个
  • additionalProperty,把参数拆成 PropertyValue 并带单位
  • isSimilarTo、isVariantOf 这类关系字段,页面上真有对应关系时再用

一个「价格面议」的工业泵页面可以这样写:

代码语言:json
复制
{
  "@context": "https://schema.org",
  "@type": "Product",
  "name": "304 不锈钢离心泵 CB-25",
  "sku": "CB-25",
  "mpn": "CB-25-SS",
  "image": [
    "https://example.com/img/cb-25-1.jpg",
    "https://example.com/img/cb-25-2.jpg"
  ],
  "description": "304 不锈钢卧式离心泵,流量 25 m³/h,扬程 32 m。价格按配置与订购数量报价,最小起订量 10 台。",
  "brand": { "@type": "Brand", "name": "Example Pumps" },
  "category": "工业泵/离心泵",
  "material": "304 不锈钢",
  "additionalProperty": [
    { "@type": "PropertyValue", "name": "流量", "value": 25, "unitCode": "MQH" },
    { "@type": "PropertyValue", "name": "扬程", "value": 32, "unitCode": "MTR" },
    { "@type": "PropertyValue", "name": "进口口径", "value": 65, "unitCode": "MMT" },
    { "@type": "PropertyValue", "name": "最小起订量", "value": 10, "unitCode": "C62" }
  ]
}

注意这段里没有 offers。unitCode 用 UN/CEFACT 代码:MQH 是立方米每小时,MTR 是米,MMT 是毫米,C62 是「个」。拿不准就改用 "unitText": "m³/h",别硬凑代码。

页面上得有对应的话

结构化数据必须和可见内容一致。正文里要能一眼找到这几句,AI 拿不到结构化数据里的价格时,就会来找这些句子:

  • 价格:按配置与数量报价
  • 最小起订量:10 台
  • 交期:确认配置后 5 个工作日内
  • 报价需要提供:流量、扬程、介质、电压

这几行本来也是询价表单该问的字段,写出来不算额外工作量。

询价入口怎么标

询价本质是一次联系行为。表单页用 ContactPage(或 WebPage 加 mainEntity)描述就够了,不需要给 Product 挂一个自定义 action,指望搜索引擎识别成「询价按钮」——schema.org 里没有这个语义,挂了也不会被当成可执行动作。

产品页上如果确实有可执行的功能(比如按型号查替代料的查询框),那描述这个页面本身更准确,用 WebPage 就够了。

WordPress 里生成时怎么防止写错

最常见的来源是主题或插件里的示例 JSON-LD 没删。生成时加一道判断:后台没填真实价格,就不输出 offers。

代码语言:php
复制
add_action('wp_head', function () {
    if (!is_singular('product')) {
        return;
    }
    $id   = get_queried_object_id();
    $data = [
        '@context'    => 'https://schema.org',
        '@type'       => 'Product',
        'name'        => get_the_title($id),
        'description' => wp_strip_all_tags(get_the_excerpt($id)),
        'image'       => array_values(array_filter([
            get_the_post_thumbnail_url($id, 'full'),
        ])),
        'sku'   => get_post_meta($id, '_sku', true),
        'brand' => [
            '@type' => 'Brand',
            'name'  => get_post_meta($id, '_brand', true),
        ],
        'additionalProperty' => array_map(
            fn($row) => [
                '@type'    => 'PropertyValue',
                'name'     => $row['name'],
                'value'    => $row['value'],
                'unitText' => $row['unit'],
            ],
            (array) get_post_meta($id, '_specs', true)
        ),
    ];

    // 只有后台确实填了价格才写 offers
    $price = get_post_meta($id, '_price', true);
    if (is_numeric($price) && (float) $price > 0) {
        $data['offers'] = [
            '@type'         => 'Offer',
            'price'         => (string) $price,
            'priceCurrency' => get_post_meta($id, '_currency', true) ?: 'CNY',
            'availability'  => 'https://schema.org/InStock',
            'url'           => get_permalink($id),
        ];
    }

    $clean = array_filter($data, static function ($v) {
        return $v !== null && $v !== '' && $v !== [];
    });

    printf(
        '<script type="application/ld+json">%s</script>' . PHP_EOL,
        wp_json_encode($clean, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
    );
}, 20);

_specs 为空时 additionalProperty 会被 array_filter 去掉,这是对的;但如果你希望没有参数的产品页也保留这个字段,就别让它进过滤。

上线后怎么验

抓一份渲染后的 HTML,看有几个 JSON-LD 块、里面有没有价格和评分:

代码语言:bash
复制
curl -s "https://example.com/products/cb-25/" -o page.html
python3 - <<'PY'
import re, json
html = open('page.html', encoding='utf-8').read()
blocks = re.findall(r'<script[^>]+application/ld\+json[^>]*>(.*?)</script>', html, re.S)
print(len(blocks), 'JSON-LD blocks')
for b in blocks:
    d = json.loads(b)
    print(d.get('@type'), '| offers:', 'offers' in d, '| rating:', 'aggregateRating' in d)
PY

要看到的是:只有一个 Product 块(主题一份、插件一份是最常见的重复),offers: False,rating: False。多出来的块要么来自主题示例,要么来自某个默认开着的开关,去对应位置关掉。

改完上线,在 Search Console 的增强功能里看商品相关报告有没有新增错误。没有富媒体展示不算错,是这套配置的正常结果。

定价策略后来变了(比如决定公开起价),回头改 JSON-LD 这一步最容易忘,把它写进改价清单里一起做。结构化数据这块我们做成了免费插件 AumViso,schema、llms.txt、sitemap、meta 一起输出:https://aumcreate.com/plugins/aumviso?utm_source=tencent&utm_medium=content&utm_campaign=tencent-product-schema-no-price-inquiry。用不用插件都行,关键是「没有价格就不输出 offers」这条规则要落到生成逻辑里,而不是靠人记得。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 先分清这是哪种页
  • 没有价格就不要写 offers
  • Product 里真正值得写的字段
  • 页面上得有对应的话
  • 询价入口怎么标
  • WordPress 里生成时怎么防止写错
  • 上线后怎么验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档