跳到正文
prodid

发布者指南

发布你的产品

向 prodid 发布,就是在网上放两个文件,在 DNS 里加一条记录。在你自己的域名上,无需注册,也无需保管任何密钥:域名本身就是凭证,修改文件就能修改或撤回你发布的内容。

你打算如何发布?

方式 1

在自己的域名上发布

两个文件加一条 DNS 记录。代表商户发布的平台在每个商户域名上做同样的事,因此每个商户都保有自己的身份和可信度等级。

已完成 0 / 4 步
x
  1. 提供发现文档

    一个位于固定路径的文件,列出你的产品 feed 在哪里:https://acme.example/.well-known/prodid.json

    .well-known/prodid.jsonapplication/json
    {
    	"$type": "org.prodid.feed",
    	"version": 1,
    	"publisher": { "name": "Acme Tekstil", "contact": "data@acme.example" },
    	"license": "CC0-1.0",
    	"feeds": ["https://acme.example/prodid/items.ndjson"]
    }
    spec/fixtures/v1/examples/prodid.json 中的示例,直接由该文件渲染。
  2. 提供 feed

    feed 是 NDJSON:每行一个完整的 JSON 对象,UTF-8,以换行分隔。外面不包数组,行与行之间没有逗号。这样,两百万件产品的 feed 也能逐行流式读取,一行出错只损失那一行,不影响其余部分。

    prodid/items.ndjsonapplication/x-ndjson
    {"$type":"org.prodid.item","key":"TJ-2041-NVY-M","brand":"Acme","name":"Trail Jacket","lang":"en","group":"TJ-2041","variant":{"color":"navy","size":"M"},"identifiers":[{"scheme":"gtin","value":"09506000134352"},{"scheme":"mpn","value":"TJ-2041-NVY-M"}],"markets":["TR","DE"],"properties":{"material":"100% recycled polyester","madeIn":"TR","weight":{"value":480,"unit":"g"}},"media":[{"url":"https://acme.example/img/tj2041-navy.webp","license":"CC-BY-4.0","kind":"image"}]}
    {"$type":"org.prodid.item","key":"TJ-2041-NVY-L","brand":"Acme","name":"Trail Jacket","lang":"en","group":"TJ-2041","variant":{"color":"navy","size":"L"},"identifiers":[{"scheme":"gtin","value":"09506000134406"},{"scheme":"mpn","value":"TJ-2041-NVY-L"}],"markets":["TR","DE"],"properties":{"material":"100% recycled polyester","madeIn":"TR","weight":{"value":505,"unit":"g"}},"media":[{"url":"https://acme.example/img/tj2041-navy.webp","license":"CC-BY-4.0","kind":"image"}]}
    {"$type":"org.prodid.item","key":"TJ-2041-OLV-M","brand":"Acme","name":"Trail Jacket","lang":"en","group":"TJ-2041","variant":{"color":"olive","size":"M"},"identifiers":[{"scheme":"gtin","value":"09506000134413"},{"scheme":"mpn","value":"TJ-2041-OLV-M"}],"markets":["TR"],"properties":{"material":"100% recycled polyester","madeIn":"TR","weight":{"value":480,"unit":"g"}},"media":[{"url":"https://acme.example/img/tj2041-olive.webp","license":"CC-BY-4.0","kind":"image"}]}
    来自 spec/fixtures/v1/examples/items.ndjson 的同一产品的三个变体。它们共享一个 group,因此索引据此构建一个包含三个变体的系列。
  3. 在 DNS 中认领身份

    文件上线后,发布一条把你自己的域名作为主机的记录。

    _prodid.acme.example TXT
    _prodid.acme.example. IN TXT "v=prodid0; host=acme.example"
  4. 通知索引已有变更

    可选。每个已知域名都会按计划重新抓取,ping 只是让下一次抓取提前。

    请索引立即运行发现
    curl -X POST https://prodid.org/ping \
      -H 'content-type: application/json' \
      -d '{"domain": "acme.example"}'
    
    HTTP/1.1 202 Accepted
    Content-Type: application/json
    
    {"status":"accepted"}

方式 2

委托托管,保留身份

很多制造商拥有域名,却无法在上面放文件。feed 托管在别处,域名用 DNS 证明,所以来源身份仍然是域名,可信度仍然是 verified。在 publish.prodid.org 创建站点并输入你的域名,它会显示需要添加的确切记录,并替你检查。

具体是什么样

已完成 0 / 4 步
x
  1. 上传到托管 slug 的目录

    ,例如 acme.prodid.org,它同时提供发现文档和 feed。

  2. 你所拥有域名上的一条 TXT 记录

    ,指向那台主机。是主机而不是 URL,因此记录永远无法把抓取程序引向任意地址。

    _prodid.acme.example TXT
    _prodid.acme.example. IN TXT "v=prodid0; host=acme.prodid.org"
  3. 一份回指你域名的文档。

    DNS 说“我的文档在那边”;文档说“我代表那个域名”。没有 domain 的委托文档会被拒绝:缺失永远不会被当作同意,正是这一点阻止了任何人把记录指向别人的 feed。

    acme.prodid.org/.well-known/prodid.jsonapplication/json
    {
    	"$type": "org.prodid.feed",
    	"version": 1,
    	"domain": "acme.example",
    	"publisher": { "name": "Acme Tekstil", "contact": "data@acme.example" },
    	"license": "CC0-1.0",
    	"feeds": ["https://acme.prodid.org/feeds/items.ndjson"]
    }
    来自 spec/fixtures/v1/examples/prodid.delegated.json。与方式 1 唯一的区别是 domain 字段,而且在这里它是必填的。
  4. 创建你的站点

    托管发布服务只有在亲自看到你的 TXT 记录之后,才会把 domain 写进文档,因此不存在某个文档认领了一个并未提出请求的域名的时间窗口。

方式 3

没有域名也能发布

已完成 0 / 1 步
x
  1. 创建你的站点

    完全没有域名的生产者,以自己的名义在托管 slug <slug>.prodid.org 上发布。在 publish.prodid.org 申请一个。来源身份是 slug 主机,可信度是 unverified,因为没有证明任何关于域名的事情。这些记录是真正的记录:标识符、解析、来源归属一应俱全。

检查你的域名

发布完成了吗?输入你的域名。索引会立即去查看它,然后你会进入它的实时状态页。

下一次抓取会在几分钟内更新状态。

ping 之前先检查文件

prodid-batch check 完全按照索引的方式校验你的发现文档和每个 feed,不需要 token,也不向索引询问任何东西。它在仓库的克隆中用 Bun 1.4.4 运行。把文件本身交给它:以 .json 结尾的路径按单个文档读取,其他路径按 NDJSON feed 读取。

像索引一样校验你提供的内容
git clone https://github.com/productdevbook/prodid
cd prodid
bun install --frozen-lockfile
curl -fsSo prodid.json https://acme.example/.well-known/prodid.json
curl -fsSo items.ndjson https://acme.example/prodid/items.ndjson
bun apps/batch/src/cli.ts check prodid.json items.ndjson

prodid.json: ok, 1 record
items.ndjson: ok, 3 records

没有问题的文件会输出 ok,以及索引会从中获取的记录数。否则,每个问题输出一行,格式为 items.ndjson:12: message,带上所在的 feed 行号,并以非零状态退出。它读的是文件,而不是你的 DNS 或服务器,所以上面清单中的 TXT 记录、内容类型和缓存头仍需你自己检查。

记录校验所依据的规则在规范中,schema 位于 /spec/schemas/v1,/spec/fixtures/v1 中有机器可读的测试向量,可以在任何人抓取之前用来测试你的导出程序。

规范只以英文发布,以英文文本为准。

现状: Spec v1。索引和托管发布服务运行在 prodid.org 上。任何人都可以发布,可以用自己的域名,也可以使用托管。 本页的文件格式,就是你 ping 索引时它读取的格式。

参考

prodid 是开源项目。帮助它成长。

给仓库加星,让更多人发现它;告诉我们哪里有问题;提交修复;或者无需 GitHub 账号,直接在这里给我们留言。