关闭

Tryaivo™技术

本地商家站补 LocalBusiness,先拆掉自评星标

2026-11-11 03:13:42 浏览:

本地商家站补 LocalBusiness,先拆掉自评星标

一句话结论:本地服务站的 JSON-LD 大多不是没有,而是打错了类型又硬塞自评评分——按 "最具体子类型 + 两个必填 + 营业时间格式" 三处修一遍,20 分钟能落地,且不会因为 aggregateRating 让整块标记失去星标资格。

背景:首页里那两块 JSON-LD,通常不是 LocalBusiness

很多本地商家站的标记来源不是人写的,而是主题或插件几年前自动输出的 Organization 块——电话是旧的,logo 已经 404,地址停在搬家前。

2026-11-11 本机对 4 个美国连锁本地服务品牌首页做了实测(直接请求原始 HTML,正则抽 application/ld+json 块,逐块 JSON.parse):

站点HTTPHTML 字节JSON-LD 块数解析错误出现的 @typeopeningHoursSpecificationaggregateRating
jiffylube.com20097,78220Organization, WebSite0 条0 个
midas.com200453,18320Organization, WebPage0 条0 个
aspendental.com403(站点侧拦截)——————
mrrooter.com403(站点侧拦截)——————

可抓的两站合计 4 块 JSON-LD,LocalBusiness 及其任何子类型出现 0 次,营业时间规格 0 条,评分 0 个。标记"合法且能解析",但 Google 从里面读不到"这是一家什么店、在哪、几点开门"。这就是本地商家站最常见的一种沉默失败:验证器不报错,实体却没被描述。

落地清单一:先把类型选对,再谈字段

Google 的 LocalBusiness 文档要求用最贴合的具体子类型,LocalBusiness 只是兜底。schema.org 的层级大致是:

LocalBusiness
├── HomeAndConstructionBusiness → Plumber / Electrician / RoofingContractor
├── AutomotiveBusiness → AutoRepair / AutoWash / AutoDealer
├── FoodEstablishment → Restaurant / CafeOrCoffeeShop / Bakery
├── MedicalBusiness → Dentist / Optician / Physiotherapy
├── HealthAndBeautyBusiness → HairSalon / NailSalon / DaySpa
└── Store / ProfessionalService / EntertainmentBusiness ...

三条判断规则:

  1. 能落到叶子就落叶子。水管工写 Plumber,不要写 LocalBusiness;牙科写 Dentist。

  2. 一个商家确实是两件事时用类型数组,Google 明确接受:"@type": ["Plumber", "HVACBusiness"]。

  3. 不要用 additionalType 补充业务类别——Google 的文档写明不支持,写了等于没写。

落地清单二:必填只有两个,但推荐字段有格式硬要求

按 Google LocalBusiness 文档口径(查询于 2026-11-11):必填仅 name 与 address,其余为推荐。但几个推荐字段带格式规则,写错不会报错、只会被忽略:

字段格式要求反例
telephone主号码,含国家码与区号(512) 555-0142
geo经纬度,至少 5 位小数30.26, -97.74(城市中心点)
priceRange少于 100 字符一整句"免费上门估价,价格透明"
url该门店自身的完整 URL,且必须能访问跳到品牌首页
sameAs商家自己拥有的资料页猜出来的点评页地址
image可访问的门店/车辆/团队图404 的 logo

一份可以直接抄的完整块(示例主体为虚构水管公司,域名与电话均使用保留示例值,落地时全部替换为真实且页面上可见的信息):

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Plumber",
  "@id": "https://harborlaneplumbing.example/#business",
  "name": "Harbor Lane Plumbing",
  "url": "https://harborlaneplumbing.example/",
  "telephone": "+1-512-555-0142",
  "image": "https://harborlaneplumbing.example/img/van.jpg",
  "priceRange": "$$",
  "address": {
    "@type": "PostalAddress",
    "streetAddress": "100 Example Ave, Suite 2",
    "addressLocality": "Austin",
    "addressRegion": "TX",
    "postalCode": "78701",
    "addressCountry": "US"
  },
  "geo": {
    "@type": "GeoCoordinates",
    "latitude": 30.26715,
    "longitude": -97.74306
  },
  "openingHoursSpecification": [
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
      "opens": "07:00:00",
      "closes": "19:00:00"
    },
    {
      "@type": "OpeningHoursSpecification",
      "dayOfWeek": "Saturday",
      "opens": "08:00:00",
      "closes": "14:00:00"
    }
  ],
  "sameAs": ["https://www.facebook.com/example-page"]
}
</script>

@id 不花钱,但值钱:后面在服务页、文章页引用这家公司时,直接 {"@id": "https://...#business"} 指回去,实体不会被拆成两个人。

落地清单三:营业时间,格式比内容更容易错

营业时间是这块标记里最容易长期漂移的部分:门店改了周六营业时间,页脚更新了,JSON-LD 三年没动。Google 的格式规则:

情形写法
常规时段opens / closes 用 hh:mm:ss,dayOfWeek 写 "Monday" 或数组
24 小时营业"opens": "00:00", "closes": "23:59"
全天休息"opens": "00:00", "closes": "00:00"
跨午夜(如周五 18:00 到次日 02:00)单独一条,18:00:00 → 02:00:00
季节性 / 节假日追加 validFrom / validThrough,格式 YYYY-MM-DD
全年不变省略 validFrom / validThrough

节假日闭店叠加在常规时段之上,像这样:

{
  "@type": "OpeningHoursSpecification",
  "dayOfWeek": "Thursday",
  "opens": "00:00:00",
  "closes": "00:00:00",
  "validFrom": "2026-11-26",
  "validThrough": "2026-11-26"
}

如果站点是 CMS,让营业时间来自同一份数据源——页脚渲染用什么,JSON-LD 就用什么。这一处改动能挡掉绝大多数"标记与页面不一致"。静态站至少把两者放进同一个 partial,让改动的人一眼看到另一处。

落地清单四:先看页面上已经有什么,再动手加

插件、主题、标签管理器都会往页面里注入 JSON-LD。动手前先跑一遍控制台,把所有块和它们的 @type 列出来:

[...document.querySelectorAll(&#x27;script[type="application/ld+json"]&#x27;)]
  .map((s, i) => {
    try {
      const data = JSON.parse(s.textContent);
      const items = [].concat(data[&#x27;@graph&#x27;] || data);
      return { block: i, types: items.map(x => x[&#x27;@type&#x27;]) };
    } catch (e) {
      return { block: i, error: e.message };
    }
  });

如果出现两个 LocalBusiness 类型块、电话还不一样,先解决冲突,别急着加第三块。上面 4 站实测里 jiffylube 与 midas 都是 2 块,各由不同来源注入——这正是冲突的高发形态。

服务端批量核验同理,本机用 Python 标准库就能跑(正则抽块 → JSON.parse → 统计类型与字段):

import re, json, urllib.request

def audit(url):
    html = urllib.request.urlopen(
        urllib.request.Request(url, headers={&#x27;User-Agent&#x27;: &#x27;Mozilla/5.0&#x27;}), timeout=20
    ).read().decode(&#x27;utf-8&#x27;, &#x27;ignore&#x27;)
    blocks = re.findall(r&#x27;<script[^>]*type=["\&#x27;]application/ld\+json["\&#x27;][^>]*>(.*?)</script>&#x27;, html, re.S | re.I)
    types, errors, hours = [], 0, 0
    for b in blocks:
        try:
            d = json.loads(b.strip())
        except Exception:
            errors += 1
            continue
        for it in (d if isinstance(d, list) else [d]):
            t = it.get(&#x27;@type&#x27;)
            types += t if isinstance(t, list) else [t]
            hours += len(it.get(&#x27;openingHoursSpecification&#x27;) or [])
    return {&#x27;blocks&#x27;: len(blocks), &#x27;parseErr&#x27;: errors, &#x27;types&#x27;: sorted(set(filter(None, types))), &#x27;hours&#x27;: hours}

print(audit(&#x27;https://www.jiffylube.com/&#x27;))

落地清单五:三道验证

  1. Rich Results Test(search.google.com/test/rich-results):贴线上 URL 或代码,errors 必修,warnings 通常是缺推荐字段。

  2. Schema Markup Validator(validator.schema.org):按完整 schema.org 词汇表校验,能抓到 adress 这类拼写错误——只面向 Google 的工具会直接忽略它。

  3. Search Console 的网址检查:确认页面可被抓取,没被 robots.txt 或 noindex 挡住。Google 明说重新抓取可能要几天,别承诺"周五前生效"。

结果:没有数字,有三处可观察的变化

按 Google 自己的说明,结构化数据"不保证会出现在搜索结果里",它解决的是"让机器别把你的信息读错",不是排名开关。本次落地没有 CTR、曝光、排名数据可报,能确认的是三件事:

  1. 自评星标不再占位:很多商家站把 Google 评分硬编码进 aggregateRating 想换星标。按 Google 评论摘录规范,如果被评论的实体自己控制了这些评论(商家在自己的站上标自己的评分),其页面用 LocalBusiness 或任何 Organization 类型都不具备星标资格。也就是说这块标记不会出星,只增加不一致风险——直接删掉,评论给人看。

  2. 重复块消失:插件与手写块并存时电话、地址会打架;合并成单一实体(统一 @id)后,"哪个地址是对的"这类人工核对不再发生。

  3. 营业时间不再漂移:用同一数据源渲染页脚与 JSON-LD 后,"页面写着周六开门、标记里还是旧的"这类不一致不再出现。

本机 4 站抽样给出的定性判断是:本地服务站的标记问题不是缺代码,而是缺实体——4 块标记里 0 个 LocalBusiness 子类型,等于把最该说清楚的事(这是什么业务、在哪、几点开)留空了。

复盘:3 条动作 + 2 条红线

该做的三件事:

  1. 类型落到最具体的子类型(Plumber、Dentist、AutoRepair),确有两项业务才用类型数组;不要用 additionalType 补类别。

  2. name + address 之外,优先补齐 telephone(含国家码)、geo(≥5 位小数)、priceRange(<100 字符)、url(门店页本身)——这四项是格式最容易写错又最容易被忽略的。

  3. 营业时间与页面共用一份数据源,跨午夜/节假日按 validFrom+validThrough 单条表达,别用"每天 24 小时"蒙过去。

两条红线(别这么做):

  1. 别给自己打 aggregateRating:商家在自家站标自家评分,Google 评论摘录规则下不具备星标资格,属于"标了也没用,还可能被判定不一致"。

  2. 别标记用户看不见的内容:营业时间、服务区域、价格区间没在页面上展示,就不要写进 JSON-LD。Google 通用结构化数据指南明确要求"不要标记页面读者看不到的内容"。

标注

  • @type:LocalBusiness(含子类型 Plumber、Dentist、AutoRepair 等);配套 PostalAddress、GeoCoordinates、OpeningHoursSpecification。

  • Schema.org 版本:现行版,查询于 2026-11-11(当日 schema.org/version/latest 连接超时,未取到具体版本号;最近已知版本为 v30.1,2026-09-16 发布)。

  • 验证工具与时间:Google Rich Results Test、Schema Markup Validator(validator.schema.org)、Search Console 网址检查;本机 Python 标准库抽样脚本运行于 2026-11-11。

  • 数据口径:4 站抽样的状态码、字节数、块数、字段计数为 2026-11-11 本机直接请求原始 HTML 得到,可复跑;结构化数据"不保证出现在搜索结果"、LocalBusiness 必填与推荐字段格式规则、评论摘录的自评资格限制,均取自 Google Search Central 公开文档口径。全文不含 CTR、曝光、排名、AI 引用变化数据,效果为结构性观察。

  • 来源:https://dev.to/leadreef_ai/localbusiness-structured-data-the-20-minute-fix-most-small-business-sites-are-missing-1cng (案例与字段写法);Google Search Central《Local business (LocalBusiness) structured data》《Review snippet》《General structured data guidelines》;schema.org Plumber、Dentist 类型页。

  • 标签:Schema.org、结构化数据、JSON-LD、AI可见度、LocalBusiness