重要提示:此文档不适用于您当前选择的格式电子邮件!
amp-access
描述
提供 AMP 付费墙和订阅支持。
必需的脚本
<script async custom-element="amp-access" src="https://cdn.ampproject.org/v0/amp-access-0.1.js"></script>
AMP 访问或“AMP 付费墙和订阅支持”使发布商可以控制读者可以访问哪些内容,以及基于读者的订阅状态、浏览次数和其他因素的限制。
与 amp-subscriptions 的关系
amp-subscriptions
扩展提供了与 amp-access
类似的功能。但是,它支持更专业的访问付费墙协议。一些值得注意的差异是
amp-subscriptions
授权响应类似于 amp-access 授权,但它是严格定义和标准化的。amp-subscriptions
扩展允许为页面配置多个服务,以参与访问/付费墙决策。它们会并发执行,并根据哪个服务返回肯定响应来确定优先级。- 允许 AMP 查看器根据与发布商的独立协议,为
amp-subscriptions
提供签名的授权响应作为访问证明。 - 在
amp-subscriptions
中,内容标记是标准化的,允许应用和爬虫轻松检测高级内容部分。
由于标记的标准化、多提供程序支持和改进的查看器支持,建议新的发布商和付费墙提供商实现使用 amp-subscriptions
。
解决方案
所提出的解决方案使发布商可以控制以下决策和流程
- 创建和维护用户
- 计量控制(允许一定数量的免费浏览)
- 负责登录流程
- 负责验证用户身份
- 负责访问规则和授权
- 在每个文档的基础上灵活控制访问参数
该解决方案包括以下组件
- AMP 阅读器 ID:由 AMP 生态系统提供,这是 AMP 所见的阅读器的唯一标识符。
- 访问内容标记:由发布商编写,定义在哪些情况下文档的哪些部分可见。
- 授权端点:由发布商提供,返回说明读者可以消费文档的哪个部分的响应。
- 回传端点:由发布商提供,用于发送文档的“查看”印象。
- 登录链接和登录页面:允许发布商验证读者身份,并将他们的身份与 AMP 阅读器 ID 连接起来。
Google AMP 缓存使用访问内容标记返回给读者文档,其中某些部分被隐藏。AMP 运行时调用授权端点,并使用响应来隐藏或显示访问内容标记中定义的不同部分。在文档显示给读者后,AMP 运行时会调用回传端点,发布商可以使用该端点来更新倒计时计量器(已使用的免费浏览次数)。
该解决方案还允许发布商在 AMP 文档中放置一个登录链接,该链接会启动登录/订阅页面,发布商可以在该页面验证读者身份,并将读者在其系统中的身份与 AMP 阅读器 ID 相关联。
在其基本形式中,此解决方案将完整的(尽管被隐藏的)文档发送给读者,并根据授权响应简单地显示/隐藏受限部分。但是,该解决方案还提供了“服务器”选项,其中受限部分可以从初始文档传递中排除,并且仅在授权确认后下载。
支持 AMP 访问要求发布商实施上述组件。需要访问内容标记和授权端点。回传端点和登录页面是可选的。
AMP 阅读器 ID
为了帮助访问服务和用例,AMP 访问引入了阅读器 ID 的概念。
阅读器 ID 是由 AMP 生态系统创建的匿名且唯一的 ID。它对于每个读者/发布商对都是唯一的 - 一个读者对于两个不同的发布商的标识不同。它是一个不可逆的 ID。阅读器 ID 包含在所有 AMP/发布商通信中,并且具有非常高的熵。发布商可以使用阅读器 ID 来识别读者,并将其映射到他们自己的身份系统。
阅读器 ID 在用户设备上构建,旨在长期存在。但是,它遵循正常的浏览器存储规则,包括隐身窗口的规则。阅读器 ID 的预期生命周期为两次使用之间 1 年,或者直到用户清除其 Cookie。阅读器 ID 当前不在设备之间共享。
阅读器 ID 的构建方式类似于用于构建 ExternalCID 的机制,如此处所述。一个示例阅读器 ID 是 amp-OFsqR4pPKynymPyMmplPNMvxSTsNQob3TnK-oE3nwVT0clORaZ1rkeEz8xej-vV6
。
AMP 访问和 Cookie
发布商可以使用自己的身份验证 Cookie,也可以依赖阅读器 ID,或者两者结合使用。
访问内容标记
访问内容标记根据从授权端点返回的授权响应确定哪些部分可见或隐藏。它是通过特殊的标记属性描述的。
授权端点
授权是由发布商提供的端点,由 AMP 运行时或 Google AMP 缓存调用。它是一个带有凭据的 CORS GET 端点。此端点返回访问参数,内容标记可以使用这些参数来隐藏或显示文档的不同部分。
回传端点
回传是由发布商提供的端点,由 AMP 运行时或 Google AMP 缓存调用。它是一个带有凭据的 CORS POST 端点。当读者开始查看文档时,AMP 运行时会自动调用此端点。在读者成功完成登录流程后,也会调用此端点。回传的主要目标之一是供发布商更新计量信息。
回传是可选的。可以通过将 noPingback
配置属性设置为 true
来禁用它。
登录页面和登录链接
登录页面由发布商实现和提供,并由 AMP 运行时调用。它通常显示为浏览器对话框。
当读者点击登录链接时会触发登录页面,发布商可以将登录链接放置在文档中的任何位置。
规范 v0.1
配置
所有端点都在 AMP 文档的 HEAD 中配置为 JSON 对象
<script id="amp-access" type="application/json"> { "property": value, ... } </script>
此配置中定义了以下属性
属性 | 值 | 描述 |
---|---|---|
authorization | <URL> | 授权端点的 HTTPS URL。 |
pingback | <URL> | 回传端点的 HTTPS URL。 |
noPingback | true/false | 当为 true 时,禁用回传。 |
login | <URL> 或 <Map[string, URL]> | 登录页面的 HTTPS URL 或不同类型的登录页面的一组 URL。 |
authorizationFallbackResponse | <object> | 如果授权响应失败,则使用 JSON 对象代替。 |
authorizationTimeout | <number> | 授权请求被视为失败后的超时时间(以毫秒为单位)。默认值为 3000。仅在开发环境中允许大于 3000 的值。 |
type | "client" 或 "server" | 默认值为 "client"。“服务器”选项正在设计讨论中,这些文档将在准备就绪后更新。 |
namespace | string | 默认值为空。如果指定了多个访问提供程序,则需要命名空间。 |
<URL> 值指定带有替换变量的 HTTPS URL。替换变量在下面的访问 URL 变量部分中详细介绍。
以下是 AMP 访问配置的示例
<script id="amp-access" type="application/json"> { "authorization": "https://pub.com/amp-access?rid=READER_ID&url=SOURCE_URL", "pingback": "https://pub.com/amp-ping?rid=READER_ID&url=SOURCE_URL", "login": "https://pub.com/amp-login?rid=READER_ID&url=SOURCE_URL", "authorizationFallbackResponse": {"error": true} } </script>
多个访问提供程序
可以使用数组而不是单个对象来指定多个访问提供程序,并为每个条目提供一个 namespace
。
<script id="amp-access" type="application/json"> [ { "property": value, ... "namespace": value }, ... ] </script>
访问 URL 变量
在配置各种端点的 URL 时,发布者可以使用替换变量。这些变量的完整列表在AMP 变量规范中定义。此外,本规范还添加了一些特定于访问的变量,例如 READER_ID
和 AUTHDATA
。下表描述了一些最相关的变量
变量 | 描述 |
---|---|
READER_ID | AMP 阅读器 ID。 |
AUTHDATA(字段) | 授权响应中字段的值。 |
RETURN_URL | AMP 运行时为登录对话框返回到的返回 URL 的占位符。 |
SOURCE_URL | 此 AMP 文档的源 URL。如果文档是从 CDN 提供的,则 AMPDOC_URL 将是 CDN URL,而 SOURCE_URL 将是原始源 URL。 |
AMPDOC_URL | 此 AMP 文档的 URL。 |
CANONICAL_URL | 此 AMP 文档的规范 URL。 |
DOCUMENT_REFERRER | 引荐来源 URL。 |
VIEWER | AMP 查看器的 URL。 |
RANDOM | 一个随机数。有助于避免浏览器缓存。 |
这是一个使用阅读器 ID、规范 URL、引荐来源信息和随机缓存清除器扩展 URL 的示例
https://pub.com/access? rid=READER_ID &url=CANONICAL_URL &ref=DOCUMENT_REFERRER &_=RANDOM
AUTHDATA 变量可用于 Pingback 和登录 URL。它允许将授权响应中的任何字段作为 URL 参数传递。例如,AUTHDATA(isSubscriber)
。也允许使用嵌套表达式,例如 AUTHDATA(other.isSubscriber)
。如果使用命名空间,则可以将命名空间前置到字段,例如 AUTHDATA(anamespace.afield)
。
访问内容标记
访问内容标记描述哪些部分是可见的或隐藏的。它由两个 AMP 属性组成:amp-access
和 amp-access-hide
,它们可以放置在任何 HTML 元素上。
amp-access
属性提供了基于授权端点返回的授权响应而产生真或假的表达式。结果值指示元素及其内容是否可见。
amp-access
值是以类 SQL 语言定义的布尔表达式。语法在附录 A 中定义。它定义如下:
<div amp-access="expression">...</div>
属性和值指的是授权端点返回的授权响应的属性和值。这提供了一个灵活的系统来支持不同的访问场景。如果使用命名空间,只需将命名空间前置到属性名称,例如 anamespace.aproperty
。
amp-access-hide
属性可用于在收到授权响应之前以乐观的方式隐藏该元素,该响应可能会显示它。它提供了“默认不可见”的语义。授权稍后返回的授权响应可能会撤销此默认值并使该部分可见。省略 amp-access-hide
属性时,该部分将默认显示/包含。amp-access-hide
属性只能与 amp-access
属性结合使用。
<div amp-access="expression" amp-access-hide>...</div>
如果授权请求失败,则不评估 amp-access
表达式,并且某个部分是否可见或隐藏取决于文档最初提供的 amp-access-hide
属性是否存在。
我们可以根据需要扩展 amp-access-*
属性集,以支持不同的混淆和渲染需求。
如果授权请求失败并且文档中未指定“authorizationFallbackResponse”响应,则不评估 amp-access
表达式,并且某个部分是否可见或隐藏取决于文档最初提供的 amp-access-hide
属性是否存在。
这是一个示例,根据订阅状态显示登录链接或完整内容
<header> Title of the document </header> <div> First snippet in the document. </div> <div amp-access="NOT subscriber" amp-access-hide> <a on="tap:amp-access.login">Become a subscriber now!</a> </div> <div amp-access="subscriber"> Full content. </div>
这里
- subscriber 是授权端点返回的授权响应中的布尔字段。此部分默认隐藏,这是可选的。
- 此示例选择乐观地显示完整内容。
这是另一个示例,向阅读器显示有关计量状态的免责声明
<section amp-access="views <= maxViews"> <template amp-access-template type="amp-mustache"> You are reading article {{views}} out of {{maxViews}}. </template> </section>
这是一个向高级订阅者显示附加内容的示例
<section amp-access="subscriptonType = 'premium'"> Shhh… No one but you can read this content. </section>
授权端点
授权通过AMP 访问配置部分中的 authorization
属性配置。它是一个经过身份验证的 CORS GET 端点。有关此请求应如何保护,请参阅CORS 来源安全。
授权可以接受访问 URL 变量部分中定义的任何参数。例如,它可以传递 AMP 阅读器 ID 和文档 URL。必须包含 READER_ID
。
此端点生成授权响应,该响应可用于内容标记表达式以显示/隐藏内容的不同部分。
请求格式为
https://publisher.com/amp-access.json? rid=READER_ID &url=SOURCE_URL
响应是一个自由格式的 JSON 对象:它可以包含任何属性和值,但有一些限制。限制如下:
- 属性名称必须符合
amp-access
表达式语法(参见附录 A)定义的限制。这主要意味着属性名称不能包含空格、破折号和其他不符合“amp-access”规范的字符。 - 属性值只能是以下类型之一:字符串、数字、布尔值。
- 值也可以嵌套为具有相同类型(字符串、数字、布尔值)值的对象。
- 序列化授权响应的总大小不能超过 500 字节。
- 请确保响应不包含任何个人身份信息 (PII) 或个人数据。
以下是可能从授权端点返回的属性的一些想法
- 计量信息:允许的最大查看次数和当前查看次数。
- 阅读器是否已登录或是否为订阅者。
- 更详细的订阅类型:基本、高级
- 地理位置:国家/地区、区域、自定义发布区域
这是一个示例,说明当阅读器不是订阅者且按每月 10 篇文章计量且已查看 6 篇文章时
{ "maxViews": 10, "currentViews": 6, "subscriber": false }
这是一个示例,说明当阅读器已登录并且具有高级订阅类型时
{ "loggedIn": true, "subscriptionType": "premium" }
此 RPC 可能会在预渲染阶段调用,因此不应用于计量倒计时,因为阅读器可能永远不会真正看到文档。
另一个重要的考虑因素是,在某些情况下,AMP 运行时可能需要在每次文档展示时多次调用授权端点。当 AMP 运行时认为阅读器的访问参数已发生重大更改时,可能会发生这种情况,例如在成功登录流程之后。
授权响应可以被 AMP 运行时和扩展程序用于三个不同的目的
- 在评估
amp-access
表达式时。 - 在评估
<template>
模板(例如amp-mustache
)时。 - 在使用
AUTHDATA(字段)
时,向 pingback 和登录 URL 提供其他变量。
AMP 运行时将授权端点作为经过身份验证的 CORS 端点调用。因此,它必须实现 CORS 协议。它应使用 CORS 来源和源来源来限制对该服务的访问,如CORS 来源安全中所述。此端点可能会使用发布者 cookie 来满足其需求。例如,它可以关联阅读器 ID 和发布者自己的用户身份之间的绑定。AMP 本身不需要知道这一点(并且更愿意不知道)。有关更多详细信息,请参阅AMP 阅读器 ID和AMP 访问和 Cookie文档。
AMP 运行时(或者更确切地说是浏览器)在调用授权端点时会观察缓存响应标头。因此,可以重用缓存的响应。这可能是也可能不是理想的。如果不是理想的,则发布者可以使用适当的缓存控制标头和/或端点 URL 的 RANDOM
变量替换。
如果授权请求失败,AMP 运行时将回退到“authorizationFallbackResponse”,如果在配置中指定了该响应。在这种情况下,授权流程将正常进行,并使用“authorizationFallbackResponse”属性的值代替授权响应。如果未指定“authorizationFallbackResponse”,则授权流程将失败,在这种情况下,将不会评估 amp-access
表达式,并且某个部分是否可见或隐藏将由文档最初提供的 amp-access-hide
属性的存在情况来确定。
授权请求会自动超时,并在 3 秒后被假定为失败。
AMP 运行时在授权流程期间使用以下 CSS 类
- 当授权流程开始时,
amp-access-loading
CSS 类设置在文档根上,并在授权流程完成或失败时删除。 - 当授权流程失败时,
amp-access-error
CSS 类设置在文档根上。
在“服务器”选项中,对授权端点的调用由 Google AMP 缓存作为简单的 HTTPS 端点进行。这意味着在这种情况下无法传递发布者的 cookie。
回传端点
Pingback 通过AMP 访问配置部分中的 pingback
属性配置。它是一个经过身份验证的 CORS POST 端点。有关此请求应如何保护,请参阅CORS 来源安全。
Pingback URL 是可选的。可以使用 "noPingback": true
禁用它。
Pingback URL 可以接受访问 URL 变量部分中定义的任何参数。例如,它可以传递 AMP 阅读器 ID 和文档 URL。必须包含 READER_ID
。
Pingback 不会生成响应 - AMP 运行时会忽略任何响应。
当阅读器开始查看文档并且阅读器已成功完成登录流程后,会调用 Pingback 端点。
发布者可以选择使用 pingback
- 来倒数页面的免费查看次数
- 将 AMP 阅读器 ID 映射到发布者的身份,因为作为经过身份验证的 CORS 端点,Pingback 可能包含发布者 cookie
请求格式为
https://publisher.com/amp-pingback? rid=READER_ID &url=SOURCE_URL
登录页面
登录页面的 URL 通过AMP 访问配置部分中的 login
属性配置。
配置可以指定单个登录 URL 或按登录类型键控的登录 URL 映射。单个登录 URL 的示例
{ "login": "https://publisher.com/amp-login.html?rid={READER_ID}" }
多个登录 URL 的示例
{ "login": { "signin": "https://publisher.com/signin.html?rid={READER_ID}", "signup": "https://publisher.com/signup.html?rid={READER_ID}" } }
该 URL 可以接受访问 URL 变量部分中定义的任何参数。例如,它可以传递 AMP 阅读器 ID 和文档 URL。可以使用 RETURN_URL
查询替换来指定返回 URL 的查询参数,例如 ?ret=RETURN_URL
。返回 URL 是必需的,如果未指定 RETURN_URL
替换,则将自动注入该 URL,默认的查询参数名称为“return”。
登录页面只是一个普通的网页,没有特殊限制,只是它应该作为浏览器对话框正常工作。有关更多详细信息,请参阅登录流程部分。
请求格式为
https://publisher.com/amp-login.html? rid=READER_ID &url=SOURCE_URL &return=RETURN_URL
请注意,如果未指定 RETURN_URL
替换,则 AMP 运行时会自动添加“return”URL 参数。登录页面完成其工作后,它必须使用以下格式重定向回指定的“返回 URL”
RETURN_URL#success=true|false
请注意 URL 哈希参数“success”的使用。该值是“true”或“false”,具体取决于登录是成功还是已放弃。理想情况下,登录页面在可能的情况下,会在成功或失败的情况下发送信号。
如果返回 success=true
信号,则 AMP 运行时将重复调用授权和 Pingback 端点以更新文档的状态,并使用新的访问配置文件报告“查看”。
登录链接
发布者可以选择将登录链接放置在文档内容的任何位置。
一个或多个登录 URL 通过AMP 访问配置部分中的“login”属性配置。
登录链接可以在任何允许使用 "on" 属性的 HTML 元素上声明。通常,这将是一个锚点或按钮元素。当配置单个登录 URL 时,其格式为
<a on="tap:amp-access.login">Login or subscribe</a>
当配置多个登录 URL 时,其格式为 tap:amp-access.login-{type}
。例如:
<a on="tap:amp-access.login-signup">Subscribe</a>
当使用命名空间时,其格式为 tap:amp-access.login-{namespace}
或 tap:amp-access.login-{namespace}-{type}
。
AMP 不区分登录和订阅。这种区分可以由发布商使用多个登录 URL/链接或在发布商端进行配置。
与 amp-analytics 集成
与 amp-analytics 的集成文档请参见 amp-access-analytics.md。
CORS 来源安全
授权和回传端点是 CORS 端点,它们必须实现 AMP CORS 安全规范 中描述的安全协议。
计量
计量是一种系统,在该系统中,读者可以在一段时间内免费查看一些文档,以便查看优质内容。一旦达到某个配额,就会启动付费墙,并且读者会看到带有追加销售信息和注册/登录链接的部分内容。例如,计量可以定义为“读者每月可以免费阅读 10 篇文章”。
AMP Access 提供了以下用于实现计量访问的工具:
- 应该使用 READER_ID 来存储计量信息。由于发布商不能依赖于始终能够在第三方上下文中设置 cookie,因此该数据应存储在服务器端。
- “阅读计数”只能在回传端点中更新。
- 只有唯一的文档才能计入配额。也就是说,刷新同一个文档十次构成一次查看。为此,授权和回传端点可以注入
SOURCE_URL
或类似的 URL 变量。请参见 访问 URL 变量。
首次点击免费
Google 的“首次点击免费”(FCF)政策在此处 进行了描述,最新的更新在 此处 进行了更详细的描述。
为了实施 FCF,发布商必须 (1) 能够确定每次查看的引荐服务,以及 (2) 能够计算每个读者每天的查看次数。
这两个步骤都由 AMP Access 规范涵盖。可以使用 访问 URL 变量 中描述的 DOCUMENT_REFERRER
URL 替换将引荐来源注入到授权和回传 URL 中。可以使用服务器端的回传端点完成查看计数。这与 计量 中描述的计量实现非常相似。
登录流程
AMP 以第一方窗口、弹出窗口或选项卡的形式启动登录对话框。在可能的情况下,AMP 查看器应尝试在浏览器上下文中启动登录对话框,以便它可以利用顶级浏览器 API。
当读者激活登录链接时,AMP 运行时会启动登录流程,并且在描述上,它遵循以下步骤:
- AMP 运行时或查看器为指定的登录 URL 打开登录对话框(第一方窗口)。该 URL 包含一个额外的“返回 URL”URL 查询参数 (
&return=RETURN_URL
)。还有许多其他参数可以扩展到 URL 中,例如读者 ID。有关更多详细信息,请参见 登录页面 部分。 - 发布商显示自由格式的登录页面。
- 读者按照登录步骤操作,例如输入用户名/密码或使用社交登录。
- 读者提交登录。发布商完成身份验证,设置 cookie,最后将读者重定向到之前请求的“返回 URL”。重定向包含一个 URL 哈希参数
success
,它可以是true
或false
。 - 登录对话框遵循重定向到“返回 URL”。
- AMP 运行时重新授权文档。
只有步骤 2-5 需要发布商处理:发布商仅提供自己的登录页面,并确保在完成后正确重定向。登录页面没有其他特殊限制,只需确保它可以用作对话框即可。
与往常一样,读者 ID 应包含在对登录页面的调用中,并且发布商可以使用它进行身份映射。作为第一方窗口,发布商还将收到他们的 cookie,并且可以设置它们。如果发现读者已经在发布商端登录,建议发布商立即使用 success=true
响应重定向回“返回 URL”。
AMP 词汇表
- AMP 文档 - 遵循 AMP 格式并由 AMP 验证器验证的 HTML 文档。AMP 文档可由 Google AMP Cache 缓存。
- AMP 验证器 - 一个计算机程序,对 HTML 文档执行静态分析,并根据文档是否符合 AMP 格式返回成功或失败。
- AMP 运行时 - 执行 AMP 文档的 JavaScript 运行时。
- Google AMP Cache - 用于 AMP 文档的代理缓存。
- AMP 查看器 - 显示/嵌入 AMP 文档的 Web 或本机应用程序。
- Publisher.com - AMP 发布商的站点。
- CORS 端点 - 跨域 HTTPS 端点。有关更多信息,请参见 https://mdn.org.cn/en-US/docs/Web/HTTP/Access_control_CORS。有关如何确保此类请求的安全,请参见 CORS 来源安全。
- 读者 - 查看 AMP 文档的实际人员。
- AMP 预渲染 - AMP 查看器可以利用预渲染,在显示之前渲染一个隐藏的文档。这可以显著提高性能。但是,重要的是要考虑到文档预渲染不构成查看,因为读者可能永远不会实际看到该文档。
修订
- 2016-09-02: "noPingback" 配置属性和可选回传。
- 2016-03-03:登录后重新发送回传 (v0.5)。
- 2016-02-19:更正了示例,从 URL 变量替换中删除了
{}
。 - 2016-02-15:配置 和 授权端点 现在允许 "authorizationFallbackResponse" 属性,该属性可以在授权失败时使用。
- 2016-02-11:授权端点 中的授权请求超时。
- 2016-02-11:现在允许嵌套字段引用,例如
object.field
。 - 2016-02-09:首次点击免费 和 计量 部分。
- 2016-02-03:向 CORS 来源安全 添加了“来源来源”安全规范。
- 2016-02-01:可以使用 RETURN_URL URL 替换自定义登录页面的 “return” 查询参数。
附录 A:“amp-access”表达式语法
最新的 BNF 语法可在 access-expr-impl.jison 文件中找到。
此语法的关键摘录如下:
search_condition: search_condition OR search_condition | search_condition AND search_condition | NOT search_condition | '(' search_condition ')' | predicate predicate: comparison_predicate | truthy_predicate comparison_predicate: scalar_exp '=' scalar_exp | scalar_exp '!=' scalar_exp | scalar_exp '<' scalar_exp | scalar_exp '<=' scalar_exp | scalar_exp '>' scalar_exp | scalar_exp '>=' scalar_exp truthy_predicate: scalar_exp scalar_exp: literal | field_ref field_ref: field_ref '.' field_name | field_name literal: STRING | NUMERIC | TRUE | FALSE | NULL
请注意,amp-access
表达式由 AMP 运行时和 Google AMP Cache 评估。这不是发布商需要实现的规范的一部分。此处仅供参考。
详细讨论
本节将详细解释 amp-access 规范的底层设计,并阐明设计选择。即将推出。
验证
请参见 AMP 验证器规范中的 amp-access 规则。
您已经阅读本文档十几次了,但它并没有真正涵盖您所有的问题?也许其他人也有同样的感觉:在 Stack Overflow 上联系他们。
转到 Stack Overflow 发现错误或缺少功能?AMP 项目强烈鼓励您的参与和贡献!我们希望您能成为我们开源社区的长期参与者,但也欢迎您为自己特别感兴趣的问题做出一次性贡献。
转到 GitHub