商品模块
一张带立即购买按钮的商品卡片。它的结账方式字段决定点击后实际跳转到哪里。**MailInApp 结账(Stripe)**内置一套真实的支付流程:无需搭建商店,无需另建结账页面,卡片信息也绝不会经过 MailInApp 自己的服务器。链接到外部商店结账则会把买家直接送到你自己 Shopify/WooCommerce 商店的商品页面,适合你更想把这笔销售(以及它的库存、税费、折扣)留在你已经在运营的商店里的情况。
MailInApp 结账(Stripe)
这是该模块的默认模式,本节内容全部针对这一模式——另一种模式请见下方的改为链接至你自己商店的结账。请先在设置 → 付款中连接你自己的 Stripe 账户(Stripe Connect,Standard/OAuth);每一笔款项都会直接结算到该账户。
与投票或评分不同,一笔购买只能在 Stripe 自己的托管结账页面上安全完成,因此该模块完全没有邮件内的动态层级。立即购买在任何地方(包括邮件本身)都优先以链接形式呈现。点击它总是先打开托管的实时预览,进入一个确认页面(/v/[token]/act?blockId=...&blockType=product&action=buy),该页面会重新展示商品的名称和价格,并要求再点一次("继续付款")才会真正创建任何东西。
这种"先确认再 POST"的形式是刻意设计的:一个会预取邮件中每个链接的安全扫描器或企业代理,绝不能仅凭一次普通的 GET 请求就触发一次真实的 Stripe Checkout Session。只有从确认页面发出的显式 POST 才会到达 POST /api/checkout。该路由始终在服务器端从模块自身存储的配置中解析价格、名称和库存,绝不使用客户端提交的任何内容。随后它会在商品所有者已连接的 Stripe 账户上创建一个 Checkout Session,写入一条 pending 状态的订单,并以 303 跳转到 Stripe。
一条 pending 订单目前还不算作一笔销售。只有 POST /api/webhooks/stripe 才会把订单状态变为 paid。它由 Stripe 自身的签名进行认证,与倒计时和打开跟踪端点所用的 HMAC 签名 URL 属于同一种信任模型,因为买家浏览器落地的成功跳转页面本身只是用户体验,不能作为付款凭证。
在该 Webhook 中,MailInApp 会在确认之前以事务方式重新核对库存。如果两位买家同时争抢最后一件商品且都通过了 Stripe 的支付,落败一方的扣款会被自动退款,并收到一封通知邮件,而不会让商品被静默超卖。一笔已确认的购买还会写入一条 purchase 互动事件,因此这笔收入会流经与其他任何模块的响应一样的汇总统计和项目 Webhook 管道。参见互动与分析。
订单履行取决于订单履行字段:
- 数字商品——你直接在模块中填写交付内容(下载链接或代码);Webhook 一确认付款,该内容就会自动通过邮件发送给买家。
- 实体商品——Stripe Checkout 会在支付流程中收集收货地址;订单会保留在项目的"订单"表格中,直到你点击标记为已发货,系统才会给买家发送一封发货通知邮件。
库存是一个可选的上限(0 = 不限)。已发送的 HTML 在发送时是静态的,这与倒计时模块的截止日期、会议链接模块的开放窗口所遵循的约定相同,因此设置了上限的商品,其库存状态不会被固定写死为文字。取而代之的是,邮件中嵌入一张服务器端渲染的小型库存提示图片("仅剩 3 件" / "已售罄"),每次打开时都会重新生成,因此不会在发送数天后仍显示过时的库存状态。在托管的实时预览中,库存会实时动态核验:一旦已付款订单数达到上限,立即购买会被直接替换为一个禁用的"已售罄"控件,而不只是在仍可点击的按钮旁加一个徽章。无论哪种情况,Webhook 在付款时的事务性重新核验才是真正的权威来源;徽章和禁用按钮只是用户体验上的便利,而不是真正的强制机制。
如果你已连接 Shopify 或 WooCommerce 商店,这些字段上方会出现一个从商店导入搜索框,列出该商店自己商品目录中的商品。它会在后台自动保持同步,无需按任何单独的按钮。选择一件商品会为你自动填好名称、描述、图片和价格。
当该同步商品拥有一个已知的商店页面(Shopify 自己的商品 handle,或 WooCommerce 的页面 URL)时,导入它还会把结账方式切换为链接到外部商店结账,并把那个页面填入外部商品页面 URL。这样导入的商品就已经可以在你自己的商店里销售了,不需要再配置任何东西。如果一件商品是在你的商店连接开始记录页面 URL 之前同步的,它会仍然保持在MailInApp 结账模式,底层不会有任何变化。
这是一次性拷贝,不是实时链接。之后每个字段依然由你自行编辑,结账时实际收取的价格永远是该模块当前保存的值,绝不会重新从商店拉取。无论是否连接了商店,下面这些字段的工作方式都相同——导入只是一个捷径,不是必要条件。
改为链接至你自己商店的结账
把结账方式切换为链接到外部商店结账,并设置一个外部商品页面 URL——你的 Shopify 商品页面、一个购物车永久链接、一个 WooCommerce 商品页面,或任意 https:// 链接——即可完全跳过 MailInApp 自己的支付流程。此时立即购买的行为与一个普通的链接按钮或链接图片完全相同:没有确认页面,没有 /api/checkout,没有 Stripe。点击依然会被追踪(因此计入点击热力图),买家会直接落地到你自己的商店去完成购买。
由于 MailInApp 从不参与这笔支付,上面提到的 MailInApp 结账相关机制没有一项适用于外部商品。没有 pending/paid 订单,"订单"表格中没有条目,没有订单履行或退款操作,没有库存强制或库存状态徽章,也没有购买触发的旅程步骤。这类收入的追踪方式,和你在自己商店中追踪任何其他销售的方式一样。Shopify 订单与结账收入跟踪介绍了如何把商店端的购买行为归因回促成它的那封邮件。
如果结账方式设置为外部,而外部商品页面 URL留空,或不是一个有效的 https:// 链接,该模块会静默回退为与 MailInApp 结账模式完全相同的行为,而不是渲染一个失效的按钮。
单品折扣
一旦某个模块是通过从商店导入填充的(因此它带有一个真实的 storeProductId,而不是手动输入的 URL),并且结账方式设置为外部,就会出现一个单品折扣开关。打开它,并设置折扣类型(百分比或固定金额折扣)、折扣数值,以及有效期(发送后天数)。就在每位收件人的邮件渲染之前,MailInApp 会在你连接的 Shopify 或 WooCommerce 商店上铸造一个一次性折扣码——仅限该收件人本人、且仅限这一件商品使用,而不是整个商店——并把立即购买重写为一个兑换链接,让购物者返回该商品自己的页面,同时折扣码已自动应用。这与发送页面上项目级别的折扣优惠(参见折扣优惠)相互独立:一个项目可以使用其中一个、两者都用,或者都不用,而且各自维护自己的冷却期,因此二者不会互相阻塞。如果某个模块的商品不是从已连接的商店导入的,会显示一条说明该开关为何被隐藏的提示。完整流程见Shopify 商品折扣码和WooCommerce 商品折扣码。
如果某位收件人的折扣码铸造失败——没有匹配的商店客户、令牌需要重新连接、实时 API 出现短暂故障——他们的邮件依然会正常发送;立即购买只会回退为该模块普通的、不带折扣的商品链接。
可配置字段:
- 名称、描述、图片——从你的媒体库中选取,而不是手动输入 URL,或者由上方的从商店导入自动填入。
- 价格和货币(USD、EUR 或 GBP)——无论哪种模式都会显示在卡片上,在外部模式下仅作为信息展示。
- 结账方式——MailInApp 结账(Stripe)或链接到外部商店结账。
- 外部商品页面 URL——仅外部模式使用;决定立即购买把买家带去哪里。
- 单品折扣、折扣类型、折扣数值、有效期(发送后天数)——仅外部模式使用,且仅在该模块的商品来自从商店导入时才可用。
- 订单履行——数字商品或实体商品;仅 MailInApp 结账模式使用。
- 库存——0 表示不限;仅 MailInApp 结账模式使用。
- 交付内容——仅数字商品使用;付款后发送的下载链接或代码;仅 MailInApp 结账模式使用。
- 背景色、内边距、边框、圆角半径,以及名称和描述的文字样式覆盖项。
示例
Subject
Back in stock: the Weekender Tote
周边商品发售或限量印刷特别适合这种玩法:把库存上限设为发售数量,让库存提示随着售出而传达出稀缺感。关于直接从一封促销邮件中完成销售、而不是把点击引流到另一个独立商店的更广泛模式,参见电子商务与新品发布。数字课程或电子书上线可以使用数字商品订单履行方式,让买家在付款确认的瞬间就拿到下载链接,完全不需要任何人工履单步骤。销售实体附加产品(印有品牌的物品、季节限定礼盒)的本地商家可以使用实体商品订单履行方式,把"订单"表格当作一个轻量级的订单队列来使用,每发出一件就标记一次已发货。如果某个地址需要确认,可以使用联系买家打开一张支持工单。
静态回退效果是什么样子
<div style="margin:12px 0;padding:16px;border:1px solid #e5e7eb;
border-radius:8px;background-color:#ffffff">
<p style="margin:0 0 4px;font-weight:600;font-size:16px;color:#111827">
Limited edition tote bag
</p>
<p style="margin:0 0 10px;font-weight:700;font-size:18px">$29.00</p>
<img src="https://mailinapp.com/api/product-status?p=proj123&b=prod-1&s=..."
width="180" height="30" alt="" style="display:block;margin-bottom:8px" />
<a href="https://mailinapp.com/v/eyJhbGci.../act?blockId=prod-1&blockType=product&action=buy"
style="display:inline-block;padding:10px 20px;background-color:#4f46e5;
color:#ffffff;border-radius:6px;text-decoration:none;
font-size:14px;font-weight:600">
Buy now
</a>
</div>
库存状态图片只有在设置了库存上限时才会渲染;立即购买始终会先打开确认页面,而不是直接在邮件内部提交一笔付款。
在外部结账模式下,完全没有确认页面或库存徽章——立即购买是一个直接指向外部商品页面 URL的、带点击追踪的普通链接:
<div style="margin:12px 0;padding:16px;border:1px solid #e5e7eb;
border-radius:8px;background-color:#ffffff">
<p style="margin:0 0 4px;font-weight:600;font-size:16px;color:#111827">
Limited edition tote bag
</p>
<p style="margin:0 0 10px;font-weight:700;font-size:18px">$29.00</p>
<a href="https://mailinapp.com/v/eyJhbGci.../click?blockId=prod-1&blockType=product&dest=https%3A%2F%2Fshop.example.com%2Fproducts%2Ftote-bag"
style="display:inline-block;border:none;border-radius:6px;
background-color:#4f46e5;color:#ffffff;padding:10px 20px;
font-size:14px;font-weight:600;text-decoration:none">
Buy now
</a>
</div>
相关内容
- 模块参考总览
- 订单、订单履行与退款
- 支持工单
- 互动与分析
- Shopify / WooCommerce —— 连接一个商店以获得"从商店导入"选择器
- Shopify 订单与结账收入跟踪 —— 把你自己商店结账页面上产生的购买行为,归因回发送它们的那封邮件
- Shopify 商品折扣码 / WooCommerce 商品折扣码 —— 直接从该模块铸造单品折扣