基于Tag通过MailChimp API发送邮件时Segment创建报错排查
问题描述
我正在用PHP直接调用MailChimp API,未使用官方库。需要给受众中带有指定Tag的订阅者子集发送新闻通讯,未来该群体规模将达数千人,因此不想先获取订阅者邮箱再发送,而是希望利用MC的Segment功能实现。
我定义Segment的代码如下:
$segmentData = [ 'name' => $segmentName, 'options' => [ 'match' => 'any', 'conditions' => [ [ 'condition_type' => 'Tags', 'field' => 'tags', 'op' => 'contains', 'value' => [$tagName] ], ], ], ];
但持续收到错误:
"errors":[{ "field":"options.conditions.item:0", "message":"Data did not match any of the schemas described in anyOf." }]
我有一个包含约20名订阅者的测试受众,其中一名订阅者带有“notify_region”标签。尝试了多种变体均无效,请问该需求是否可行?我是否遗漏了什么?以下是完整测试代码:
<?php $apiKey = 'YOUR_MAILCHIMP_API_KEY'; $listId = 'YOUR_LIST_ID'; $templateId = 'YOUR_TEMPLATE_ID'; $tagName = 'notify_region'; $segmentName = 'Example Segment 1'; function callMailchimp($method, $endpoint, $data = []) { global $apiKey; $apiUrl = "https://us10.api.mailchimp.com/3.0"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $apiUrl . $endpoint); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($ch, CURLOPT_USERPWD, "user:$apiKey"); if (!empty($data)) { curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json' ]); } $response = curl_exec($ch); curl_close($ch); return json_decode($response, true); } $segmentData = [ 'name' => $segmentName, 'options' => [ 'match' => 'any', // 'match' => 'all', 'conditions' => [ [ 'condition_type' => 'Tags', 'field' => 'tags', 'op' => 'contains', 'value' => [$tagName] // 'value' => [ $tagName ], ], ], ], ]; $segmentResponse = callMailchimp('POST', "/lists/$listId/segments", $segmentData); if (isset($segmentResponse['id'])) { $segmentId = $segmentResponse['id']; $campaignData = [ 'type' => 'regular', 'recipients' => [ 'list_id' => $listId, 'segment_opts' => [ 'saved_segment_id' => $segmentId, ], ], 'settings' => [ 'subject_line' => 'Notification for Region', 'from_name' => 'Company', 'from_email' => 'hello@example.com', 'template_id' => $templateId, ], ]; $campaignResponse = callMailchimp('POST', '/campaigns', $campaignData); if (isset($campaignResponse['id'])) { $campaignId = $campaignResponse['id']; // $sendResponse = callMailchimp('POST', "/campaigns/$campaignId/actions/send"); // if(isset($sendResponse['message']) && $sendResponse['message'] === 'Campaign send started'){ // echo "Campaign sent successfully!"; // } else { // echo "Failed to send campaign: " . json_encode($sendResponse); // } echo "FIN."; } else { echo "Failed to create campaign: " . json_encode($campaignResponse); } } else { echo "Failed to create segment: " . json_encode($segmentResponse); }
解决方案
这个需求完全可行,出错原因是Tag类型的Segment条件参数格式不符合MailChimp API要求。针对标签的条件,不需要field和op字段,而是要使用tag_name或tag_id配合operator字段来定义:
修正后的Segment数据结构
$segmentData = [ 'name' => $segmentName, 'options' => [ 'match' => 'any', 'conditions' => [ [ 'condition_type' => 'Tags', 'tag_name' => $tagName, // 直接指定标签名称,大小写敏感 'operator' => 'contains' // 可选值:contains / not_contains ], ], ], ];
如果已知标签ID,也可以用tag_id替换tag_name,效果一致:
[ 'condition_type' => 'Tags', 'tag_id' => 'YOUR_TAG_ID', 'operator' => 'contains' ]
完整修正后的测试代码
<?php $apiKey = 'YOUR_MAILCHIMP_API_KEY'; $listId = 'YOUR_LIST_ID'; $templateId = 'YOUR_TEMPLATE_ID'; $tagName = 'notify_region'; $segmentName = 'Example Segment 1'; function callMailchimp($method, $endpoint, $data = []) { global $apiKey; // 注意替换为API Key对应的服务器前缀(比如us10、us2等,API Key最后一段即为服务器标识) $apiUrl = "https://us10.api.mailchimp.com/3.0"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $apiUrl . $endpoint); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); curl_setopt($ch, CURLOPT_USERPWD, "user:$apiKey"); if (!empty($data)) { curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Content-Type: application/json' ]); } $response = curl_exec($ch); curl_close($ch); return json_decode($response, true); } // 修正后的Segment参数 $segmentData = [ 'name' => $segmentName, 'options' => [ 'match' => 'any', 'conditions' => [ [ 'condition_type' => 'Tags', 'tag_name' => $tagName, 'operator' => 'contains' ], ], ], ]; $segmentResponse = callMailchimp('POST', "/lists/$listId/segments", $segmentData); if (isset($segmentResponse['id'])) { $segmentId = $segmentResponse['id']; $campaignData = [ 'type' => 'regular', 'recipients' => [ 'list_id' => $listId, 'segment_opts' => [ 'saved_segment_id' => $segmentId, ], ], 'settings' => [ 'subject_line' => 'Notification for Region', 'from_name' => 'Company', 'from_email' => 'hello@example.com', 'template_id' => $templateId, ], ]; $campaignResponse = callMailchimp('POST', '/campaigns', $campaignData); if (isset($campaignResponse['id'])) { $campaignId = $campaignResponse['id']; // 取消注释即可触发发送 // $sendResponse = callMailchimp('POST', "/campaigns/$campaignId/actions/send"); // if(isset($sendResponse['message']) && $sendResponse['message'] === 'Campaign send started'){ // echo "Campaign sent successfully!"; // } else { // echo "Failed to send campaign: " . json_encode($sendResponse); // } echo "FIN. Segment ID: $segmentId, Campaign ID: $campaignId"; } else { echo "Failed to create campaign: " . json_encode($campaignResponse); } } else { echo "Failed to create segment: " . json_encode($segmentResponse); }
额外注意事项
- 确保API Key对应的服务器前缀和请求URL中的一致(API Key最后一段为服务器标识,比如
us10) - 标签名称必须和受众中实际存在的标签完全匹配,大小写敏感
- 如需匹配多个标签,可在
conditions数组中添加多个Tag条件,结合match参数(any表示满足任意一个,all表示满足所有)
内容的提问来源于stack exchange,提问作者donohoe
相关产品推荐
相关产品推荐

