Shopify + Klaviyo 实现商品到货提醒(BIS)功能

123 阅读3分钟

一、背景与目标

在 Shopify 实现 “Back in Stock” (BIS) 功能。 实现缺货商品收集用户订阅,当商品补货后自动邮件提醒用户购买,提高转化。

二、技术方案

此功能有两种实现方式:

方案 A:Klaviyo Onsite Snippet 简单快速,适合官方提供的免费主题

方案 B:Klaviyo BIS Subscription API 只使用订阅api,适合自定义主题。

方案 A:使用 Klaviyo Onsite Snippet 集成

1、将 Klaviyo 与 Shopify 集成,将数据导入 Klaviyo

help.klaviyo.com/hc/en-us/ar…

image.png

2、在 Shopify 加入 Klaviyo App

image.png

3、创建 Back in Stock flow

登录 klaviyo 后台, Flows --> Create Flow ---> 搜索 Back in Stock

4、获取 PUBLIC API KEY

登录 klaviyo 后台, Settings --> Account ---> API keys

5、在主题的 theme.liquid 中加入如下代码片段

  • </body> 标签上面插入以下代码,并替换 PUBLIC_API_KEY:
<script src="https://a.klaviyo.com/media/js/onsite/onsite.js"></script>
<script>
    var klaviyo = klaviyo || [];
    klaviyo.init({
      account: "PUBLIC_API_KEY",
      platform: "shopify"
    });
    klaviyo.enable("backinstock",{ 
    trigger: {
      product_page_text: "Notify Me When Available",
      product_page_class: "button",
      product_page_text_align: "center",
      product_page_margin: "0px",
      replace_anchor: false
    },
    modal: {
     headline: "{product_name}",
     body_content: "Register to receive a notification when this item comes back in stock.",
     email_field_label: "Email",
     button_label: "Notify me when available",
     subscription_success_label: "You're in! We'll let you know when it's back.",
     footer_content: '',
     additional_styles: "@import url('https://fonts.googleapis.com/css?family=Helvetica+Neue');",
     drop_background_color: "#000",
     background_color: "#fff",
     text_color: "#222",
     button_text_color: "#fff",
     button_background_color: "#439fdb",
     close_button_color: "#ccc",
     error_background_color: "#fcd6d7",
     error_text_color: "#C72E2F",
     success_background_color: "#d3efcd",
     success_text_color: "#1B9500"
    }
  });
</script>

6、如果主题适配,此时该功能已生效,效果如图

优缺点

✅ 优点:

  • 实现快,维护简单。
  • 补货时自动发送邮件提醒。

⚠️ 注意:

  • 只支持 shopify 官方免费主题。
  • 自定义程度有限。

方案 B:使用 Klaviyo BIS Subscription API 自定义集成

使用场景

  • 使用shopify自定义主题
  • 需要完全掌控表单样式、挂载位置以及交互体验

步骤 1~4 同方案A

5、在 buy-button.liquid 中插入表单

插入在 Buy Button 下方:

{% if product.selected_or_first_available_variant.available == false %}
  <div class="back-in-stock-form-wrapper">
    <form id="klaviyo-back-in-stock-form">
      <input type="email" id="bis-email" placeholder="Enter your email" required>
      <button type="submit">Notify Me</button>
      <p id="bis-message" style="display:none;color:green;">Thank you! You'll be notified when this product is back in stock.</p>
    </form>
  </div>
{% endif %}

6、在 global.js (或其他已引用的js)中添加脚本

使用 Klaviyo 官方推荐结构:

(简单验证,并非最终实现代码)

document.addEventListener('DOMContentLoaded', function() {
  const form = document.getElementById('klaviyo-back-in-stock-form');
  if (form) {
    form.addEventListener('submit', async function(e) {
      e.preventDefault();
      const email = document.getElementById('bis-email').value.trim();
      const message = document.getElementById('bis-message');
      const variantId = document.querySelector('[name="id"]').value;
      const klaviyoVariantId = `$shopify:::$default:::${variantId}`;

      const payload = {
        "data": {
          "type": "back-in-stock-subscription",
          "attributes": {
            "profile": {
              "data": {
                "type": "profile",
                "attributes": { "email": email }
              }
            },
            "channels": ["EMAIL"]
          },
          "relationships": {
            "variant": {
              "data": { "type": "catalog-variant", "id": klaviyoVariantId }
            }
          }
        }
      };

      try {
        const response = await fetch(`https://a.klaviyo.com/client/back-in-stock-subscriptions/?company_id=YOUR_PUBLIC_API_KEY`, {
          method: 'POST',
          headers: {
            "Content-Type": "application/json",
            "revision": "2024-06-15"
          },
          body: JSON.stringify(payload)
        });
        if (response.ok) {
          message.style.display = 'block';
          form.reset();
        } else {
          const resData = await response.json();
          console.error(resData);
          alert("Subscription failed, please try again.");
        }
      } catch (error) {
        console.error(error);
        alert("Subscription failed, please try again.");
      }
    });
  }
});

7、效果如图

三、添加配置及多语言(针对方案B)

1、添加多语言

locales/en.default.json 添加:

"back_in_stock": {
    "button": "Notify me when available",
    "title": "Notify me when available",
    "description": "Register to receive a notification when this item comes back in stock.",
    "email_placeholder": "Your email",
    "submit": "Notify me",
    "success": "Thank you! You'll be notified when this product is back in stock."
  }

替换原文案,例如"Notify me when available"替换为

{{ 'back_in_stock.button' | t }}

2、添加 Metafield

Name: Back in Stock Enabled

Namespace and key: custom.bis_enabled

Content type: True or False (Boolean)

Description: Enable Back in Stock button when sold out

image.png

主要代码

全局 js

document.addEventListener('DOMContentLoaded', function () {
  const modal = document.getElementById('bis-modal');
  const trigger = document.getElementById('bis-trigger-button');
  const close = document.getElementById('bis-close');
  const form = document.getElementById('klaviyo-back-in-stock-form');
  const message = document.getElementById('bis-message');

  if (trigger && modal && close && form) {
    // 打开 Modal
    trigger.addEventListener('click', () => {
      modal.style.display = 'flex';
    });

    // 关闭 Modal
    close.addEventListener('click', () => {
      modal.style.display = 'none';
    });

    // 点击 Modal 外层关闭
    modal.addEventListener('click', (e) => {
      if (e.target === modal) {
        modal.style.display = 'none';
      }
    });

    // 提交表单
    form.addEventListener('submit', async function (e) {
      e.preventDefault();
      const email = document.getElementById('bis-email').value.trim();
      const variantId = document.querySelector('[name="id"]').value;
      const klaviyoVariantId = `$shopify:::$default:::${variantId}`;

      const payload = {
        "data": {
          "type": "back-in-stock-subscription",
          "attributes": {
            "profile": {
              "data": {
                "type": "profile",
                "attributes": { "email": email }
              }
            },
            "channels": ["EMAIL"]
          },
          "relationships": {
            "variant": {
              "data": { "type": "catalog-variant", "id": klaviyoVariantId }
            }
          }
        }
      };

      try {
        const response = await fetch(`https://a.klaviyo.com/client/back-in-stock-subscriptions/?company_id=YOUR_PUBLIC_API_KEY`, {
          method: 'POST',
          headers: {
            "Content-Type": "application/json",
            "revision": "2024-06-15"
          },
          body: JSON.stringify(payload)
        });

        if (response.ok) {
          message.style.display = 'block';
          form.reset();
          setTimeout(() => {
            modal.style.display = 'none';
            message.style.display = 'none';
          }, 2000);
        } else {
          const resData = await response.json();
          console.error(resData);
          alert("Subscription failed, please try again.");
        }
      } catch (error) {
        console.error(error);
        alert("Subscription failed, please try again.");
      }
    });
  }
});

弹窗 liquid

{% if product.selected_or_first_available_variant.available == false
    and product.metafields.custom.bis_enabled == true
  %}
    <button
      id="bis-trigger-button"
      type="button"
      class="primary-btn"
      style="width: 100%;"
    >
      {{ 'back_in_stock.button' | t }}
    </button>

    <div
      id="bis-modal"
      style="display:none;position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);align-items:center;justify-content:center;z-index:9999;"
    >
      <div style="background:#fff;padding:30px;border-radius:6px;max-width:360px;width:90%;position:relative;">
        <button
          id="bis-close"
          style="position:absolute;top:10px;right:10px;background:none;border:none;font-size:22px;cursor:pointer;"
        >
          &times;
        </button>
        <h3
          class="heading-3"
          style="text-align: center;"
        >
          {{ product.title }}
        </h3>
        <p
          class="main-desc"
          style="margin: 10px 0;"
        >
          {{ 'back_in_stock.description' | t }}
        </p>
        <form id="klaviyo-back-in-stock-form">
          <input
            type="email"
            id="bis-email"
            placeholder="{{ 'back_in_stock.email_placeholder' | t }}"
            required
            style="width:100%;padding:10px;margin-top:10px;border:1px solid #ccc;"
          >
          <button
            type="submit"
            class="primary-btn"
            style="width: 100%;margin-top: 20px;"
          >
            {{ 'back_in_stock.submit' | t }}
          </button>
        </form>
        <p id="bis-message" style="display:none;color:green;margin-top:10px;">
          {{ 'back_in_stock.success' | t }}
        </p>
      </div>
    </div>
  {% endif %}

四、测试验证流程

✅ 创建缺货商品或设置变体库存为 0。

✅ 前端加载页面测试表单是否显示。

✅ 填写邮箱订阅后在 Klaviyo 检查是否收到 Subscription 事件。

image.png

✅ 补货该商品,验证是否触发 Back in Stock 邮件提醒。

image.png

五、参考文档

Getting started with Shopify | Klaviyo Help Center

How to enable onsite tracking for Shopify | Klaviyo Help Center

How to build a back in stock flow | Klaviyo Help Center

How to install Back in Stock for Shopify | Klaviyo Help Center

Set-up Back in Stock Notifications via API | Klaviyo Developers