一家本地企业以几十种它无法控制的形式存在于网络上:地图应用、点评网站、行业目录、数据聚合商、社交资料。每一处都保存着该企业名称、地址和电话号码的各自副本,在本地SEO中称为NAP。当企业搬迁、更换号码或更换品牌时,大多数副本仍保持原样。
结果是顾客拨打一个已停用的号码,送货司机找到旧地址,搜索引擎和地图应用对同一家企业持有相互矛盾的信息。许多较小的网站从较大的网站复制数据,因此一条错误的列表往往会扩散开来。
NAP审计能系统地发现这些不一致之处。本指南涵盖需要收集的内容、如何比较列表以使格式噪音不会淹没真正的问题、实现这一点的代码,以及如何确定修复的优先级。
NAP审计检查什么
对于企业被列出的每一个地方,审计都要回答三个问题:
- 名称: 这是企业的真实名称吗,与其店面和网站上使用的一致,没有添加关键词或旧品牌?
- 地址: 这是当前地址吗,包括套房或单元号,邮政编码正确吗?
- 电话: 这是当前的主要号码吗,而不是一个没人接听的旧线路或追踪号码?
许多审计还会检查网站URL、营业时间和主要类别,因为它们也会以同样的方式过时。下面的方法可以轻松扩展到这些方面。
第一步:写下规范记录
一切都要与一份记录进行比较:企业的NAP应该在所有地方呈现的样子。这应该来自企业本身,而不是来自某个目录,并完整地写出来:去掉法律后缀,街道地址要与邮局记录的完全一致,主要电话号码也是如此。对于多地点企业,每个地点保留一份规范记录,并配有一个稳定的ID。
这听起来很明显,但这正是大多数审计出错的地方。如果规范记录本身已经过时,那么每一次比较都会朝着同一个方向出错。
第二步:收集列表
需要收集的列表分为三组:
| 来源 | 示例 | 如何收集 |
|---|---|---|
| 主要平台 | Google Business Profile、Apple Business Connect、Bing Places、Facebook | 企业自己的仪表板和官方API |
| 点评与目录网站 | 综合及行业目录、点评平台 | 存在官方API时使用官方API,否则使用公开的列表页面 |
| 数据聚合商 | 向许多较小目录供应数据的公司 | 它们的企业门户 |
在存在官方API和企业自己账户的地方,尽量使用它们:它们更可靠,也是被允许的。对于没有API的目录,列表页面是公开的,每个企业在每个目录上收集一个页面是一项轻量且偶尔进行的任务。列表在不同国家和城市之间也可能有所不同,因此应像当地顾客那样查看它们;我们关于收集本地企业数据的指南涵盖了收集方面的内容。
准确记录所列出的原始值,连同URL和日期。审计比较的是标准化后的值,但修复工作需要确切知道每个网站上具体错在哪里。
第三步:比较时不要被噪音淹没
一个粗糙的比较会标记出几乎所有东西。“St”对比”Street”、“(312) 555-0142”对比”312-555-0142”、有无”LLC”:这些都不是真正的问题,一份充满这些内容的审计会掩盖那条仍然保留着去年电话号码的列表。
解决办法是在比较之前对每个字段进行标准化,并对结果进行分类:
| 状态 | 含义 | 优先级 |
|---|---|---|
| match(匹配) | 与规范记录相同 | 无 |
| format(格式) | 文本不同,标准化后数值相同 | 低:方便时整理 |
| close(接近) | 几乎相同,例如缺少套房号或有拼写错误 | 中:检查并修复 |
| mismatch(不匹配) | 不同的值:另一个地址、另一个号码、另一个名称 | 高:优先修复 |
| missing(缺失) | 该字段在该列表上为空 | 中:添加它 |
下面的代码以适合每个字段的方式对其进行标准化。名称会去掉标点符号、重音符号、开头的”The”以及法律后缀。地址会展开为标准缩写(“Street”变为”st”,“Suite”变为”ste”)并去掉ZIP+4扩展码。电话号码使用phonenumbers(Google电话号码库的Python移植版)进行解析,并以国际格式进行比较,因此同一号码的任何格式都能匹配。
import re
import unicodedata
from difflib import SequenceMatcher
import phonenumbers
LEGAL_SUFFIXES = {"llc", "inc", "ltd", "co", "corp", "gmbh", "plc", "sl", "srl"}
ADDRESS_WORDS = {
"street": "st", "avenue": "ave", "boulevard": "blvd", "road": "rd", "drive": "dr",
"lane": "ln", "court": "ct", "place": "pl", "suite": "ste", "floor": "fl",
"north": "n", "south": "s", "east": "e", "west": "w", "apartment": "apt", "unit": "ste",
}
def _words(text):
text = unicodedata.normalize("NFKD", text).encode("ascii", "ignore").decode().lower()
text = text.replace("&", " and ").replace("#", " ste ")
return re.sub(r"[^a-z0-9 ]+", " ", text).split()
def norm_name(name):
words = [w for w in _words(name) if w not in LEGAL_SUFFIXES]
return " ".join(words[1:] if words[:1] == ["the"] else words)
def norm_address(address):
# Drop the ZIP+4 extension, so "60607-1234" matches "60607".
address = re.sub(r"\b(\d{5})-\d{4}\b", r"\1", address)
return " ".join(ADDRESS_WORDS.get(w, w) for w in _words(address))
def norm_phone(phone, region="US"):
try:
number = phonenumbers.parse(phone, region)
except phonenumbers.NumberParseException:
return None
if not phonenumbers.is_valid_number(number):
return None
return phonenumbers.format_number(number, phonenumbers.PhoneNumberFormat.E164)
def compare(field, canonical, listed, region="US"):
"""'match', 'format' (same after normalising), 'close', 'mismatch' or 'missing'."""
if not listed:
return "missing"
if listed.strip() == canonical.strip():
return "match"
if field == "phone":
a, b = norm_phone(canonical, region), norm_phone(listed, region)
return "format" if a and a == b else "mismatch"
normalise = norm_name if field == "name" else norm_address
a, b = normalise(canonical), normalise(listed)
if a == b:
return "format"
return "close" if SequenceMatcher(None, a, b).ratio() >= 0.9 else "mismatch"
def audit(canonical, listings, region="US"):
"""One row per directory: the status of name, address and phone."""
rows = []
for source, listing in listings.items():
row = {"source": source}
for field in ("name", "address", "phone"):
row[field] = compare(field, canonical[field], listing.get(field), region)
rows.append(row)
return rows
region参数告诉电话解析器,对于写得没有国家代码的号码应假定使用哪个国家,因此同一段代码可以通过region="DE"或region="BR"用于德国或巴西的企业。地址缩写是英语的;如需用于其他市场,请扩展ADDRESS_WORDS。
运行一次审计
以下是一家企业与四个目录列表之间的审计(这是一个说明性示例,并非真实列表):
from nap import audit
canonical = {
"name": "Corner Bakery",
"address": "123 North Main Street, Suite 4, Chicago, IL 60607",
"phone": "(312) 555-0142",
}
listings = {
"Directory A": {"name": "Corner Bakery", "address": "123 N Main St #4, Chicago IL 60607",
"phone": "312-555-0142"},
"Directory B": {"name": "The Corner Bakery LLC", "address": "123 North Main Street, Suite 4, Chicago, IL 60607",
"phone": "(312) 555-0142"},
"Directory C": {"name": "Corner Bakery", "address": "88 West Lake Street, Chicago, IL 60601",
"phone": "(312) 555-0199"},
"Directory D": {"name": "Corner Bakery & Cafe", "address": "123 N Main St, Chicago, IL 60607"},
}
print(f"{'source':<12} {'name':<9} {'address':<9} phone")
for row in audit(canonical, listings):
print(f"{row['source']:<12} {row['name']:<9} {row['address']:<9} {row['phone']}")
source name address phone
Directory A match format format
Directory B format match match
Directory C match mismatch mismatch
Directory D mismatch close missing
逐行解读:
- Directory A 的地址和电话格式不同,但每个值都是正确的。无需修复。
- Directory B 在名称上加上了”The”和”LLC”。同样没问题,不过值得整理一下。
- Directory C 的名称正确,但地址和电话号码都是旧的。这是把顾客引向错误地点的列表,也是最应优先修复的一条。
- Directory D 的名称不同(“Corner Bakery & Cafe”),缺少套房号,而且根本没有电话号码。
第四步:按正确的顺序修复
- 优先处理主要平台上的不匹配。 这些列表触及的人最多,许多较小的网站会从中复制数据。
- 处理其他地方的不匹配,从与企业所在行业最相关的目录、以及在搜索该企业名称时排名靠前的目录开始。
- 缺失的字段,尤其是电话号码。
- 接近匹配,例如缺少套房号。
- 格式差异放在最后处理,如果还要处理的话。
有些列表可以通过企业自己的账户直接编辑。另一些则需要认领流程或支持请求,而数据聚合商通常需要通过其自己的门户提交更正,之后更改才会流向它们供应数据的网站。预计某些目录上的修复可能需要数周才能生效。
第五步:按计划重新审计
列表会逐渐回到旧状态。聚合商可能会覆盖更正,用户可能在某些平台上建议编辑,旧数据也可能从没人记得的来源重新浮现。对主要平台每月重新运行一次审计,对长尾目录每季度运行一次,并且在每次搬迁、电话更改或品牌重塑之后都要重新审计。
保留每次审计结果及其日期。趋势比任何一次单独的结果都更重要:如果一条列表每次更正后都会变回旧地址,这说明上游存在一个仍然持有错误数据的来源。
对于地图排名很重要的企业,可以将审计与排名测量结合起来,覆盖企业服务的整个区域。我们关于地理网格排名跟踪的指南展示了如何测量这一点,以及如何判断在列表清理完成后可见度是否有所提升。
NAP不一致的常见原因
- 搬迁和电话更改只在主要资料上更新了,而其他地方没有更新。
- 为广告活动添加的电话追踪号码,从未被移除。
- 品牌重塑后,旧名称在长尾目录上依然存在。
- 套房和单元号被没有对应字段的目录舍弃。
- 重复列表,通常是自动生成的,每一条都有各自略有不同的数据。
- 多地点企业中,某一地点的数据被复制到了另一地点的列表上。
常见问题
什么是NAP一致性?
NAP代表名称、地址和电话号码。NAP一致性是指一家企业的NAP在网上列出的每一个地方都相同且正确:地图应用、目录、点评网站以及它自己的网站。
像”St”和”Street”这样的格式差异重要吗?
比错误数据的重要性低得多。审计应该在比较之前对格式进行标准化,这样带有旧地址或旧电话号码的列表才会凸显出来,而不是淹没在无害的差异之中。
应该多久审计一次企业列表?
对主要平台每月审计一次,对其他目录每季度审计一次,这是一个合理的节奏,此外在任何搬迁、电话更改或品牌重塑之后都应额外进行一次审计。
我应该在目录列表上使用追踪电话号码吗?
使用时要谨慎。一个在广告活动结束后被移除的追踪号码,会让列表留下一个已失效的号码。如果你使用追踪号码,要确保在平台允许的情况下也列出主要号码,并记录哪些列表使用了哪个号码。
总结
NAP审计是一项数据质量工作:一份规范记录,每条列表连同其来源和日期一并收集,数值在比较之前经过标准化,结果经过分类以便真正的问题凸显出来。优先修复最大平台上的不匹配,然后依次向下处理,并按计划重新审计,因为列表会逐渐偏离。上面的代码处理比较工作;真正的功夫在于保持规范记录的正确性,并根据审计发现采取行动。