ActiveCampaign
Email checker for ActiveCampaign. Verify contacts in your email marketing automation.
将 EmailVerify 与 ActiveCampaign 集成,验证邮箱地址、清理联系人列表并提高邮件送达率。
集成方法
| 方法 | 适用场景 | 复杂度 |
|---|---|---|
| Webhook 自动化 | 实时验证 | 低 |
| API 集成 | 自定义工作流 | 中 |
| 批量导入 | 列表清理 | 低 |
方法 1:Webhook 自动化
创建一个在添加联系人时验证邮箱的自动化流程。
创建 Webhook 操作
- 前往 Automations → New Automation
- 选择触发器(例如"订阅列表")
- 添加操作 → Conditions and Workflow → Webhook
- 配置 Webhook:
URL: https://api.emailverify.ai/v1/verify
Method: POST
Headers:
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json
Body:
{
"email": "%EMAIL%",
"webhook_url": "https://yoursite.com/api/activecampaign/callback"
}创建回调处理器
处理来自 EmailVerify 的验证结果。
// pages/api/activecampaign/callback.js
import crypto from 'crypto';
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
const { email, status, result } = req.body;
// 根据验证结果更新 ActiveCampaign 中的联系人
const acApiUrl = process.env.ACTIVECAMPAIGN_API_URL;
const acApiKey = process.env.ACTIVECAMPAIGN_API_KEY;
try {
// 通过邮箱查找联系人
const searchResponse = await fetch(
`${acApiUrl}/api/3/contacts?email=${encodeURIComponent(email)}`,
{
headers: {
'Api-Token': acApiKey,
},
}
);
const searchData = await searchResponse.json();
const contact = searchData.contacts[0];
if (!contact) {
return res.status(404).json({ error: 'Contact not found' });
}
// 使用验证状态更新联系人
const fieldUpdates = {
contact: {
fieldValues: [
{
field: process.env.AC_FIELD_EMAIL_STATUS,
value: status,
},
{
field: process.env.AC_FIELD_EMAIL_SCORE,
value: result.score?.toString() || '',
},
],
},
};
await fetch(`${acApiUrl}/api/3/contacts/${contact.id}`, {
method: 'PUT',
headers: {
'Api-Token': acApiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify(fieldUpdates),
});
// 根据状态添加标签
const tagName = status === 'valid' ? 'Email Verified' : 'Email Invalid';
await addTagToContact(contact.id, tagName, acApiUrl, acApiKey);
res.status(200).json({ success: true });
} catch (error) {
console.error('ActiveCampaign update error:', error);
res.status(500).json({ error: 'Update failed' });
}
}
async function addTagToContact(contactId, tagName, apiUrl, apiKey) {
// 首先,查找或创建标签
const tagResponse = await fetch(
`${apiUrl}/api/3/tags?search=${encodeURIComponent(tagName)}`,
{
headers: { 'Api-Token': apiKey },
}
);
const tagData = await tagResponse.json();
let tagId = tagData.tags[0]?.id;
if (!tagId) {
// 如果标签不存在则创建
const createResponse = await fetch(`${apiUrl}/api/3/tags`, {
method: 'POST',
headers: {
'Api-Token': apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({
tag: { tag: tagName, tagType: 'contact' },
}),
});
const createData = await createResponse.json();
tagId = createData.tag.id;
}
// 将标签添加到联系人
await fetch(`${apiUrl}/api/3/contactTags`, {
method: 'POST',
headers: {
'Api-Token': apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({
contactTag: { contact: contactId, tag: tagId },
}),
});
}方法 2:API 集成
使用两个 API 构建自定义集成。
ActiveCampaign 服务
// services/activecampaign.js
import EmailVerify from '@emailverify/sdk';
class ActiveCampaignService {
constructor() {
this.apiUrl = process.env.ACTIVECAMPAIGN_API_URL;
this.apiKey = process.env.ACTIVECAMPAIGN_API_KEY;
this.bv = new EmailVerify(process.env.EMAILVERIFY_API_KEY);
}
async verifyContact(contactId) {
// 获取联系人详情
const contact = await this.getContact(contactId);
if (!contact?.email) {
throw new Error('Contact has no email');
}
// 验证邮箱
const result = await this.bv.verify({ email: contact.email });
// 使用验证结果更新联系人
await this.updateContactFields(contactId, {
email_status: result.status,
email_score: result.score,
email_disposable: result.is_disposable ? 'Yes' : 'No',
email_verified_at: new Date().toISOString(),
});
// 根据验证结果应用自动化
if (result.status === 'invalid') {
await this.addToAutomation(contactId, 'Invalid Email Cleanup');
}
return result;
}
async getContact(contactId) {
const response = await fetch(
`${this.apiUrl}/api/3/contacts/${contactId}`,
{
headers: { 'Api-Token': this.apiKey },
}
);
const data = await response.json();
return data.contact;
}
async updateContactFields(contactId, fields) {
const fieldValues = await this.mapToFieldValues(fields);
await fetch(`${this.apiUrl}/api/3/contacts/${contactId}`, {
method: 'PUT',
headers: {
'Api-Token': this.apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({
contact: { fieldValues },
}),
});
}
async mapToFieldValues(fields) {
// 获取自定义字段 ID
const customFields = await this.getCustomFields();
return Object.entries(fields).map(([key, value]) => ({
field: customFields[key],
value: String(value),
}));
}
async getCustomFields() {
const response = await fetch(`${this.apiUrl}/api/3/fields`, {
headers: { 'Api-Token': this.apiKey },
});
const data = await response.json();
return data.fields.reduce((acc, field) => {
acc[field.perstag.toLowerCase()] = field.id;
return acc;
}, {});
}
async addToAutomation(contactId, automationName) {
// 通过名称查找自动化
const response = await fetch(
`${this.apiUrl}/api/3/automations?search=${encodeURIComponent(automationName)}`,
{
headers: { 'Api-Token': this.apiKey },
}
);
const data = await response.json();
const automation = data.automations[0];
if (automation) {
await fetch(`${this.apiUrl}/api/3/contactAutomations`, {
method: 'POST',
headers: {
'Api-Token': this.apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({
contactAutomation: {
contact: contactId,
automation: automation.id,
},
}),
});
}
}
async verifyList(listId) {
// 获取列表中的所有联系人
const contacts = await this.getListContacts(listId);
const emails = contacts.map(c => c.email);
// 批量验证
const job = await this.bv.verifyBulk(emails);
// 等待完成
let status;
do {
await new Promise(resolve => setTimeout(resolve, 5000));
status = await this.bv.getBulkJobStatus(job.job_id);
} while (status.status !== 'completed');
// 获取结果并更新联系人
const results = await this.bv.getBulkJobResults(job.job_id);
for (const result of results.results) {
const contact = contacts.find(c => c.email === result.email);
if (contact) {
await this.updateContactFields(contact.id, {
email_status: result.status,
email_score: result.score,
});
}
}
return {
total: results.results.length,
valid: results.results.filter(r => r.status === 'valid').length,
invalid: results.results.filter(r => r.status === 'invalid').length,
};
}
async getListContacts(listId) {
const contacts = [];
let offset = 0;
const limit = 100;
while (true) {
const response = await fetch(
`${this.apiUrl}/api/3/contacts?listid=${listId}&limit=${limit}&offset=${offset}`,
{
headers: { 'Api-Token': this.apiKey },
}
);
const data = await response.json();
if (data.contacts.length === 0) break;
contacts.push(...data.contacts);
offset += limit;
}
return contacts;
}
}
export default new ActiveCampaignService();使用示例
import activeCampaign from './services/activecampaign';
// 验证单个联系人
const result = await activeCampaign.verifyContact('12345');
console.log(`Email status: ${result.status}`);
// 验证整个列表
const listResults = await activeCampaign.verifyList('1');
console.log(`Verified ${listResults.total} contacts`);
console.log(`Valid: ${listResults.valid}, Invalid: ${listResults.invalid}`);方法 3:表单集成
在提交 ActiveCampaign 表单之前验证邮箱。
自定义表单处理器
<!-- ActiveCampaign Form with EmailVerify -->
<form id="ac-form" action="https://yoursite.activehosted.com/proc.php" method="POST">
<input type="hidden" name="u" value="1" />
<input type="hidden" name="f" value="1" />
<input type="hidden" name="s" />
<input type="hidden" name="c" value="0" />
<input type="hidden" name="m" value="0" />
<input type="hidden" name="act" value="sub" />
<input type="hidden" name="v" value="2" />
<div class="form-group">
<label for="email">邮箱地址</label>
<input type="email" id="email" name="email" required />
<span id="email-status"></span>
</div>
<div class="form-group">
<label for="fullname">姓名</label>
<input type="text" id="fullname" name="fullname" />
</div>
<button type="submit" id="submit-btn">订阅</button>
</form>
<script>
const form = document.getElementById('ac-form');
const emailInput = document.getElementById('email');
const emailStatus = document.getElementById('email-status');
const submitBtn = document.getElementById('submit-btn');
let emailValid = false;
emailInput.addEventListener('blur', async function() {
const email = this.value;
if (!email) return;
emailStatus.textContent = '验证中...';
emailStatus.className = 'verifying';
submitBtn.disabled = true;
try {
const response = await fetch('/api/verify-email', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email }),
});
const result = await response.json();
if (result.status === 'valid') {
emailStatus.textContent = '✓ 邮箱有效';
emailStatus.className = 'valid';
emailValid = true;
} else {
emailStatus.textContent = '✗ 请输入有效的邮箱地址';
emailStatus.className = 'invalid';
emailValid = false;
}
} catch (error) {
// API 错误时允许提交
emailStatus.textContent = '';
emailValid = true;
}
submitBtn.disabled = false;
});
form.addEventListener('submit', function(e) {
if (!emailValid) {
e.preventDefault();
emailStatus.textContent = '请输入有效的邮箱地址';
emailStatus.className = 'invalid';
}
});
</script>
<style>
.form-group {
margin-bottom: 1rem;
}
#email-status {
display: block;
margin-top: 0.25rem;
font-size: 0.875rem;
}
#email-status.verifying { color: #666; }
#email-status.valid { color: #28a745; }
#email-status.invalid { color: #dc3545; }
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
</style>自动化工作流
订阅时验证
触发器: 联系人订阅列表
↓
操作: Webhook 调用 EmailVerify
↓
等待: 直到收到 Webhook 响应
↓
条件判断: 检查 email_status 字段
├─ 如果"valid": 继续发送欢迎邮件
└─ 如果"invalid": 添加到"无效邮箱"列表,结束定期列表清理
触发器: 每月运行一次
↓
操作: Webhook 启动批量验证
↓
等待: 24 小时(等待批量任务完成)
↓
目标: 批量验证完成
↓
操作: 通过 Webhook 回调处理结果重新激活活动
触发器: 联系人 90 天未打开邮件
↓
操作: 验证邮箱地址
↓
条件判断: 邮箱状态
├─ 如果"valid": 发送重新激活邮件
└─ 如果"invalid": 取消订阅联系人自定义字段设置
在 ActiveCampaign 中创建以下自定义字段:
| 字段名称 | 类型 | 个性化标签 |
|---|---|---|
| Email Status | 文本 | %EMAIL_STATUS% |
| Email Score | 数字 | %EMAIL_SCORE% |
| Email Disposable | 下拉框(是/否) | %EMAIL_DISPOSABLE% |
| Email Verified At | 日期 | %EMAIL_VERIFIED_AT% |
通过 API 创建字段
async function createCustomFields(apiUrl, apiKey) {
const fields = [
{ title: 'Email Status', type: 'text', perstag: 'EMAIL_STATUS' },
{ title: 'Email Score', type: 'text', perstag: 'EMAIL_SCORE' },
{ title: 'Email Disposable', type: 'dropdown', perstag: 'EMAIL_DISPOSABLE', options: ['Yes', 'No'] },
{ title: 'Email Verified At', type: 'date', perstag: 'EMAIL_VERIFIED_AT' },
];
for (const field of fields) {
await fetch(`${apiUrl}/api/3/fields`, {
method: 'POST',
headers: {
'Api-Token': apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({ field }),
});
}
}分段
根据邮箱验证状态创建分段。
有效邮箱分段
条件:
- 联系人字段"Email Status"为"valid"
- 联系人字段"Email Score"大于 0.7无效邮箱分段
条件:
- 联系人字段"Email Status"为"invalid"
或
- 联系人字段"Email Status"为"unknown"高风险邮箱分段
条件:
- 联系人字段"Email Disposable"为"Yes"
或
- 联系人字段"Email Score"小于 0.5最佳实践
1. 活动前验证
在主要活动前始终验证列表:
async function preCampaignVerification(listId, campaignId) {
const service = new ActiveCampaignService();
// 验证列表
const results = await service.verifyList(listId);
// 只有在无效率可接受时才继续
const invalidRate = results.invalid / results.total;
if (invalidRate > 0.05) { // 无效率超过 5%
console.warn(`无效率较高: ${(invalidRate * 100).toFixed(1)}%`);
console.warn('建议在发送前清理列表');
return false;
}
return true;
}2. 处理速率限制
async function verifyWithRateLimit(contacts) {
const batchSize = 100;
const delayMs = 1000;
for (let i = 0; i < contacts.length; i += batchSize) {
const batch = contacts.slice(i, i + batchSize);
await Promise.all(
batch.map(contact => verifyContact(contact.id))
);
if (i + batchSize < contacts.length) {
await new Promise(resolve => setTimeout(resolve, delayMs));
}
}
}3. 错误处理
async function safeVerify(email) {
try {
const result = await bv.verify({ email });
return result;
} catch (error) {
console.error(`验证失败 ${email}:`, error);
// 返回未知状态以允许进一步处理
return {
email,
status: 'unknown',
error: error.message,
};
}
}