跳转至主要内容

Shopify 店铺缺货商品监控 到货通知

本文提供的代码可以用于监控一个 Shopify 店铺上商品库存状态变化。

Node.js 版本

availability.js
class ProductStockMonitor {
  constructor(shopDomain, interval = 60000) {
    this.shopDomain = shopDomain;
    this.interval = interval;
    this.stockHistory = new Map();
    this.isMonitoring = false;
  }

  async getProductsStock() {
    try {
      const response = await fetch(`https://${this.shopDomain}/products.json`);
      const data = await response.json();

      return data.products.map((product) => ({
        id: product.id,
        title: product.title,
        handle: product.handle,
        variants: product.variants.map((variant) => ({
          id: variant.id,
          title: variant.title,
          available: variant.available,
          price: variant.price,
        })),
      }));
    } catch (error) {
      console.error("获取库存数据失败:", error);
      return [];
    }
  }

  checkStockChanges(newData) {
    newData.forEach((product) => {
      const previousData = this.stockHistory.get(product.id);

      if (previousData) {
        product.variants.forEach((variant) => {
          const previousVariant = previousData.variants.find(
            (v) => v.id === variant.id
          );
          if (
            previousVariant &&
            variant.available !== previousVariant.available
          ) {
            this.notifyAvailabilityChange(product, variant);
          }
        });
      }
      this.stockHistory.set(product.id, product);
    });
  }

  notifyAvailabilityChange(product, variant) {
    console.log(`库存状态变化通知: ${product.title} - ${variant.title}`);
    console.log(`状态: ${variant.available ? "有库存" : "无库存"}`);
    console.log(`价格: ${variant.price}`);
    console.log(
      `产品链接: https://${this.shopDomain}/products/${product.handle}`
    );
  }

  startMonitoring() {
    if (this.isMonitoring) return;

    this.isMonitoring = true;
    console.log("开始监控库存状态...");

    this.monitor();
    this.monitorInterval = setInterval(() => {
      this.monitor();
    }, this.interval);
  }

  stopMonitoring() {
    if (!this.isMonitoring) return;

    clearInterval(this.monitorInterval);
    this.isMonitoring = false;
    console.log("停止监控库存状态");
  }

  async monitor() {
    const products = await this.getProductsStock();
    this.checkStockChanges(products);
  }
}

// 使用示例
const monitor = new ProductStockMonitor("hypermarkup.myshopify.com", 15000); // 每15秒检查一次
monitor.startMonitoring();

可以在此基础上修改,实现邮件通知。

HTML 版本

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      class ProductStockMonitor {
        constructor(shopDomain, interval = 60000) {
          this.shopDomain = shopDomain;
          this.interval = interval;
          this.stockHistory = new Map();
          this.isMonitoring = false;
        }

        async getProductsStock() {
          try {
            const response = await fetch(
              `https://${this.shopDomain}/products.json`
            );
            const data = await response.json();

            return data.products.map((product) => ({
              id: product.id,
              title: product.title,
              handle: product.handle,
              variants: product.variants.map((variant) => ({
                id: variant.id,
                title: variant.title,
                available: variant.available,
                price: variant.price,
              })),
            }));
          } catch (error) {
            console.error("获取库存数据失败:", error);
            return [];
          }
        }

        checkStockChanges(newData) {
          newData.forEach((product) => {
            const previousData = this.stockHistory.get(product.id);

            if (previousData) {
              product.variants.forEach((variant) => {
                const previousVariant = previousData.variants.find(
                  (v) => v.id === variant.id
                );
                if (
                  previousVariant &&
                  variant.available !== previousVariant.available
                ) {
                  this.notifyAvailabilityChange(product, variant);
                }
              });
            }
            this.stockHistory.set(product.id, product);
          });
        }

        notifyAvailabilityChange(product, variant) {
          console.log(`库存状态变化通知: ${product.title} - ${variant.title}`);
          console.log(`状态: ${variant.available ? "有库存" : "无库存"}`);
          console.log(`价格: ${variant.price}`);
          console.log(
            `产品链接: https://${this.shopDomain}/products/${product.handle}`
          );
        }

        startMonitoring() {
          if (this.isMonitoring) return;

          this.isMonitoring = true;
          console.log("开始监控库存状态...");

          this.monitor();
          this.monitorInterval = setInterval(() => {
            this.monitor();
          }, this.interval);
        }

        stopMonitoring() {
          if (!this.isMonitoring) return;

          clearInterval(this.monitorInterval);
          this.isMonitoring = false;
          console.log("停止监控库存状态");
        }

        async monitor() {
          const products = await this.getProductsStock();
          this.checkStockChanges(products);
        }
      }

      // 使用示例
      const monitor = new ProductStockMonitor(
        "hypermarkup.myshopify.com",
        15000
      ); // 每15秒检查一次
      monitor.startMonitoring();
    </script>
  </body>
</html>