博客

👨🏻‍🏫 自动将 InstaWP 新闻订阅者发送到 Mailchimp 的 GraphQL Query

Leonardo Losoviz
作者:Leonardo Losoviz ·

(请阅读博客文章 🚀 自动将 InstaWP 新闻订阅者发送到 Mailchimp,了解此 Query 的背景。)

这个 GraphQL query 会捕获在 InstaWP 中创建新沙盒站点时勾选了「Subscribe to mailing list」复选框的访客的电子邮件地址,并将其订阅到 Mailchimp 列表:

query HasSubscribedToNewsletter {
  hasSubscriberOptIn: _httpRequestHasParam(name: "marketing_optin")
  subscriberOptIn: _httpRequestStringParam(name: "marketing_optin")
  isNotSubscriberOptInNAValue: _notEquals(value1: $__subscriberOptIn, value2: "NA")
  subscribedToNewsletter: _and(values: [$__hasSubscriberOptIn, $__isNotSubscriberOptInNAValue])
    @export(as: "subscribedToNewsletter")
}
 
query MaybeCreateContactOnMailchimp
   @depends(on: "HasSubscribedToNewsletter")
   @include(if: $subscribedToNewsletter)
{
  subscriberEmail: _httpRequestStringParam(name: "email")
  
  mailchimpUsername: _env(name: "MAILCHIMP_API_CREDENTIALS_USERNAME")
    @remove
  mailchimpPassword: _env(name: "MAILCHIMP_API_CREDENTIALS_PASSWORD")
    @remove
  
  mailchimpListMembersJSONObject: _sendJSONObjectItemHTTPRequest(input: {
    url: "https://us7.api.mailchimp.com/3.0/lists/{listCode}/members",
    method: POST,
    options: {
      auth: {
        username: $__mailchimpUsername,
        password: $__mailchimpPassword
      },
      json: {
        email_address: $__subscriberEmail,
        status: "subscribed"
      }
    }
  })
}

此外,您也可以将订阅者注册到您的 WordPress 新闻插件(例如:Noptin 或其他插件)中。

让我们来看看这个 GraphQL query 是如何发挥作用的。

将 GraphQL Query 拆分为独立单元

一个 GraphQL 文档可以包含多个操作(query 和 mutation),但每次只执行其中一个。我们通过 GraphQL 端点上的 ?operationName=... 参数来指定执行哪个;若未指定,则执行最后一个操作。

请注意,上面的文档中有 2 个 query 操作:

  1. HasSubscribedToNewsletter
  2. MaybeCreateContactOnMailchimp

Webhook URL 中包含 ?operationName=MaybeCreateContactOnMailchimp,因此该操作将被执行。

得益于 Multiple Query Execution 扩展,MaybeCreateContactOnMailchimp 会首先执行 HasSubscribedToNewsletter,如 @depends 指令所示:

query MaybeCreateContactOnMailchimp
   @depends(on: "HasSubscribedToNewsletter")
   # ...
{
  #
}

此外,MaybeCreateContactOnMailchimp 是条件性执行的,仅当变量 $subscribedToNewsletter 的值为 true 时才执行:

query MaybeCreateContactOnMailchimp
   @depends(on: "HasSubscribedToNewsletter")
   @include(if: $subscribedToNewsletter)
{
  #
}

$subscribedToNewsletter 是一个动态变量,在 HasSubscribedToNewsletter 操作中导出:

query HasSubscribedToNewsletter {
  # ...
  subscribedToNewsletter: _and(values: [$__hasSubscriberOptIn, $__isNotSubscriberOptInNAValue])
    @export(as: "subscribedToNewsletter")
}

因此,MaybeCreateContactOnMailchimp 操作仅在用户勾选了「Subscribe to mailing list」复选框时才会执行。

判断用户是否勾选了复选框

InstaWP 的 Webhook 文档 说明负载数据包含以下字段(以及其他字段):

  • marketing_optin:表示用户是否勾选了复选框
  • email:访客的电子邮件地址

文档仅说明当复选框未被勾选时,字段 marketing_optin 的值为 NA,因此我们需要据此进行处理。

判断用户是否勾选复选框的逻辑如下:

  • 检查字段 marketing_optin 是否存在,以及
  • 检查其值不为 NA

这一逻辑在 HasSubscribedToNewsletter 操作中完成。以下是带注释的版本,解释 query 中每一行的作用:

query HasSubscribedToNewsletter {
 
  # Check if field `marketing_optin` is present
  hasSubscriberOptIn: _httpRequestHasParam(name: "marketing_optin")
 
  # Get the value of field `marketing_optin`
  subscriberOptIn: _httpRequestStringParam(name: "marketing_optin")
 
  # Check if the value of the field is not "NA"
  isNotSubscriberOptInNAValue: _notEquals(value1: $__subscriberOptIn, value2: "NA")
 
  # Perform an AND operation: field present && value != "NA"
  subscribedToNewsletter: _and(values: [$__hasSubscriberOptIn, $__isNotSubscriberOptInNAValue])
    
    # Export the result under dynamic variable $subscribedToNewsletter
    @export(as: "subscribedToNewsletter")
}

这个 query 中有几个有趣的地方。

全局字段

您是否注意到以 _ 开头的字段?具体如下:

  • _httpRequestHasParam
  • _httpRequestStringParam
  • _notEquals
  • _and

这些是全局字段,即在 GraphQL schema 的所有类型下都可用的字段。全局字段提供的是功能而非数据,按惯例以 _ 开头。

Field to Input

您是否注意到以 $__ 开头的变量?具体如下:

  • $__subscriberOptIn
  • $__hasSubscriberOptIn
  • $__isNotSubscriberOptInNAValue

这些是动态变量,包含同一操作中在其之前定义的字段的值。例如,变量 $__subscriberOptIn 包含在其上方声明的字段 subscriberOptIn 的值。

这是由 Field to Input 扩展提供的功能,允许将一个字段的输出作为另一个字段的输入使用。这就是我们能在 GraphQL query 中创建功能逻辑的方式。

在这个 query 中,字段 isNotSubscriberOptInNAValue 检查前面查询的字段 subscriberOptIn 的值是否不等于 "NA",而 subscribedToNewsletter 则对字段 hasSubscriberOptInisNotSubscriberOptInNAValue 的值执行 AND 运算。

连接到 Mailchimp

MaybeCreateContactOnMailchimp 操作包含提取负载数据并调用 Mailchimp API 将电子邮件添加到新闻列表的逻辑。

以下是带注释的操作,解释每一行的作用:

query MaybeCreateContactOnMailchimp
   @depends(on: "HasSubscribedToNewsletter")
   @include(if: $subscribedToNewsletter)
{
  # Extract form field `email` from the body of the request
  subscriberEmail: _httpRequestStringParam(name: "email")
  
  # Obtain Mailchimp credentials, defined in wp-config.php
  mailchimpUsername: _env(name: "MAILCHIMP_API_CREDENTIALS_USERNAME")
    # Do not print the credentials in the response
    @remove
  mailchimpPassword: _env(name: "MAILCHIMP_API_CREDENTIALS_PASSWORD")
    @remove
  
  # Connect to Mailchimp to add a new member to the list
  mailchimpListMembersJSONObject: _sendJSONObjectItemHTTPRequest(input: {
    url: "https://us7.api.mailchimp.com/3.0/lists/{listCode}/members",
    method: POST,
    options: {
      # Provide credentials to connect to the API
      auth: {
        username: $__mailchimpUsername,
        password: $__mailchimpPassword
      },
      # Provide form data
      json: {
        email_address: $__subscriberEmail,
        status: "subscribed"
      }
    }
  })
}

让我们来探讨这个 query 中使用的功能。

环境变量

连接 Mailchimp API 时,我们需要提供凭据。但是,我们不希望将凭据直接写入 GraphQL query,因为它们可能在某处泄露(例如:可能被打印到某个日志中)。

因此,我们使用全局字段 _env(由 PHP Constants and Environment via Schema 扩展提供)来读取环境变量或 PHP 常量,并结合 @remove 指令(由 Field Response Removal 扩展提供)来避免在响应中打印凭据。

这样,我们就可以在 wp-config.php 中声明凭据:

define( 'MAILCHIMP_API_CREDENTIALS_USERNAME', '{ username }' );
define( 'MAILCHIMP_API_CREDENTIALS_PASSWORD', '{ password }' );

向 Mailchimp 发送 HTTP 请求

逻辑的最后一块是字段 _sendJSONObjectItemHTTPRequest,它向某个服务发送 HTTP 请求。

由于我们需要连接到 Mailchimp API,字段 mailchimpListMembersJSONObject 提供了 Mailchimp REST API 端点所需的数据,如将成员订阅到 Mailchimp 列表的文档所示:

  • 发送 POST 请求
  • 端点为 https://{subdomain}.api.mailchimp.com/3.0/lists/{listCode}/members
  • 请求体必须包含字段 email_addressstatus

创建与任意 API 交互的 Webhook

本文中的 GraphQL query 将数据从 InstaWP 转发到 Mailchimp。

您可以将同样的思路应用于任何您需要的组合:从某个源服务(无论是哪种)提取数据,对其进行适配,然后发送到某个目标服务(无论是哪种)。

祝您使用愉快!


订阅我们的新闻通讯

及时了解 Gato GraphQL 的所有更新。