交易管理
Brevo CRM 的 Deals API 让你在 Tajo 平台内部管理整条销售管道、追踪每笔交易的推进情况,并把与收入相关的工作流全部自动化。
概览
交易管理主要用于:
- 销售管道追踪:按阶段推进每笔交易,并据此生成收入预测
- 收入归因:把每笔交易与电商侧的客户行为关联起来
- 自动跟进:交易阶段一旦发生变化,立即触发跟进动作
- 团队绩效分析:追踪赢单与丢单情况,并计算转化率
- 会员计划集成:交易成交时自动发放会员积分
快速开始
创建交易
POST https://api.brevo.com/v3/crm/dealsContent-Type: application/jsonapi-key: YOUR_API_KEY
{ "name": "Acme Corp - Enterprise Loyalty Package", "attributes": { "deal_stage": "Qualified", "amount": 75000, "close_date": "2026-06-30", "pipeline": "Enterprise Sales", "deal_type": "new_business", "probability": 60, "company_id": "comp_123456789", "contact_id": "contact_987654321", "source": "inbound_lead", "loyalty_points_bonus": 5000, "contract_length_months": 12 }}响应
{ "id": "deal_abc123def456", "name": "Acme Corp - Enterprise Loyalty Package", "created_at": "2026-01-25T14:30:00Z", "updated_at": "2026-01-25T14:30:00Z"}获取交易
列出全部交易
按筛选条件和分页参数获取交易列表:
GET https://api.brevo.com/v3/crm/deals?limit=50&offset=0&sort=descContent-Type: application/jsonapi-key: YOUR_API_KEY响应
{ "items": [ { "id": "deal_abc123def456", "name": "Acme Corp - Enterprise Loyalty Package", "attributes": { "deal_stage": "Qualified", "amount": 75000, "close_date": "2026-06-30", "pipeline": "Enterprise Sales", }, "created_at": "2026-01-25T14:30:00Z", "updated_at": "2026-01-25T14:30:00Z" } ], "total": 1}按阶段筛选交易
GET https://api.brevo.com/v3/crm/deals?filters[attributes.deal_stage]=Negotiation&sort=attributes.amount:desc获取单个交易
GET https://api.brevo.com/v3/crm/deals/{deal_id}Content-Type: application/jsonapi-key: YOUR_API_KEY更新交易
更新交易属性
PATCH https://api.brevo.com/v3/crm/deals/{deal_id}Content-Type: application/jsonapi-key: YOUR_API_KEY
{ "attributes": { "deal_stage": "Negotiation", "amount": 82000, "probability": 75, "next_activity_date": "2026-02-15" }}响应
{ "id": "deal_abc123def456", "updated_at": "2026-02-01T10:15:00Z"}交易管道管理
管道阶段配置
为电商销售场景设计一套结构化的交易推进流程:
class TajoDealPipeline { constructor() { this.dealsApi = new DealsApi(); this.stages = [ { name: 'Lead', probability: 10, actions: ['qualify_lead'] }, { name: 'Qualified', probability: 25, actions: ['schedule_demo'] }, { name: 'Demo', probability: 40, actions: ['send_proposal'] }, { name: 'Proposal', probability: 60, actions: ['negotiate_terms'] }, { name: 'Negotiation', probability: 80, actions: ['finalize_contract'] }, { name: 'Closed Won', probability: 100, actions: ['onboard_customer', 'award_loyalty_points'] }, { name: 'Closed Lost', probability: 0, actions: ['analyze_loss', 'schedule_followup'] } ]; }
async advanceDealStage(dealId, newStage) { const deal = await this.dealsApi.getDeal(dealId); const stageConfig = this.stages.find(s => s.name === newStage);
if (!stageConfig) { throw new Error(`Invalid stage: ${newStage}`); }
// Update deal with new stage await this.dealsApi.updateDeal(dealId, { attributes: { deal_stage: newStage, probability: stageConfig.probability, stage_changed_at: new Date().toISOString(), previous_stage: deal.attributes.deal_stage } });
// Execute stage-specific actions for (const action of stageConfig.actions) { await this.executeStageAction(dealId, action, deal); }
return { dealId, newStage, probability: stageConfig.probability }; }
async executeStageAction(dealId, action, deal) { switch (action) { case 'award_loyalty_points': if (deal.attributes.loyalty_points_bonus > 0) { await loyaltyService.awardCorporatePoints( deal.attributes.company_id, deal.attributes.loyalty_points_bonus, { reason: 'Deal closure bonus', dealId } ); } break;
case 'onboard_customer': await this.triggerOnboardingWorkflow(deal); break;
case 'analyze_loss': await this.logDealLoss(dealId, deal); break;
case 'schedule_followup': await this.createFollowUpTask(dealId, deal); break; } }}交易预测
基于销售管道中的数据生成收入预测:
class DealForecasting { async generateForecast(pipeline, timeframe) { const deals = await this.dealsApi.getDeals({ filters: { 'attributes.pipeline': pipeline, 'attributes.close_date': `<${timeframe.end}`, 'attributes.deal_stage': '!Closed Lost' } });
const forecast = { pipeline, timeframe, totalPipeline: 0, weightedPipeline: 0, byStage: {}, byOwner: {}, byMonth: {} };
for (const deal of deals.items) { const amount = deal.attributes.amount || 0; const probability = deal.attributes.probability || 0; const weighted = amount * (probability / 100); const stage = deal.attributes.deal_stage; const owner = deal.attributes.deal_owner; const month = new Date(deal.attributes.close_date).toISOString().slice(0, 7);
forecast.totalPipeline += amount; forecast.weightedPipeline += weighted;
// Aggregate by stage if (!forecast.byStage[stage]) { forecast.byStage[stage] = { count: 0, total: 0, weighted: 0 }; } forecast.byStage[stage].count++; forecast.byStage[stage].total += amount; forecast.byStage[stage].weighted += weighted;
// Aggregate by owner if (!forecast.byOwner[owner]) { forecast.byOwner[owner] = { count: 0, total: 0, weighted: 0 }; } forecast.byOwner[owner].count++; forecast.byOwner[owner].total += amount; forecast.byOwner[owner].weighted += weighted;
// Aggregate by month if (!forecast.byMonth[month]) { forecast.byMonth[month] = { count: 0, total: 0, weighted: 0 }; } forecast.byMonth[month].count++; forecast.byMonth[month].total += amount; forecast.byMonth[month].weighted += weighted; }
return forecast; }}电商交易自动化
由订单自动创建交易
针对高价值的电商行为,自动创建对应的交易:
class EcommerceDealAutomation { async createDealFromOrder(order) { // Only create deals for high-value or B2B orders if (order.total < 5000 && !order.isB2B) return null;
const deal = { name: `${order.customerName} - Order #${order.id}`, attributes: { deal_stage: order.isB2B ? 'Qualified' : 'Proposal', amount: order.total, close_date: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), pipeline: order.isB2B ? 'Enterprise Sales' : 'E-Commerce Upsell', deal_type: 'new_business', source: 'ecommerce_order', order_id: order.id, product_categories: order.categories.join(', '), contact_id: order.contactId, company_id: order.companyId || null, loyalty_points_bonus: Math.floor(order.total * 0.1) } };
return await this.dealsApi.createDeal(deal); }
async createRenewalDeal(subscription) { const renewalDate = new Date(subscription.expiresAt); const createDate = new Date(renewalDate.getTime() - 90 * 24 * 60 * 60 * 1000);
if (new Date() < createDate) return null;
const deal = { name: `${subscription.customerName} - Renewal`, attributes: { deal_stage: 'Qualified', amount: subscription.annualValue, close_date: subscription.expiresAt, pipeline: 'Renewals', deal_type: 'renewal', probability: 70, source: 'auto_renewal', subscription_id: subscription.id, contact_id: subscription.contactId, company_id: subscription.companyId, contract_length_months: 12, loyalty_points_bonus: Math.floor(subscription.annualValue * 0.05) } };
return await this.dealsApi.createDeal(deal); }}由交易触发的会员工作流
class DealLoyaltyIntegration { async onDealStageChange(dealId, oldStage, newStage) { const deal = await this.dealsApi.getDeal(dealId);
// Award milestone points at key stages const milestoneStages = { 'Demo': 100, 'Proposal': 250, 'Closed Won': deal.attributes.loyalty_points_bonus || 1000 };
if (milestoneStages[newStage] && deal.attributes.contact_id) { await loyaltyService.awardPoints( deal.attributes.contact_id, milestoneStages[newStage], { reason: `Deal milestone: ${newStage}`, dealId } ); }
// Trigger tier evaluation on deal closure if (newStage === 'Closed Won' && deal.attributes.company_id) { const company = await this.companiesApi.getCompany(deal.attributes.company_id); const newTotal = (company.attributes.annual_spend || 0) + deal.attributes.amount;
await this.companiesApi.updateCompany(deal.attributes.company_id, { attributes: { annual_spend: newTotal, last_deal_closed: new Date().toISOString() } });
await this.tierManager.evaluateTierUpgrade(deal.attributes.company_id, newTotal); } }}交易分析
管道绩效指标
class DealAnalytics { async getPipelineMetrics(pipeline, timeframe) { const allDeals = await this.dealsApi.getDeals({ filters: { 'attributes.pipeline': pipeline } });
const closedDeals = allDeals.items.filter( d => d.attributes.deal_stage === 'Closed Won' || d.attributes.deal_stage === 'Closed Lost' );
const wonDeals = closedDeals.filter(d => d.attributes.deal_stage === 'Closed Won'); const lostDeals = closedDeals.filter(d => d.attributes.deal_stage === 'Closed Lost');
return { totalDeals: allDeals.total, openDeals: allDeals.total - closedDeals.length, wonDeals: wonDeals.length, lostDeals: lostDeals.length, winRate: closedDeals.length > 0 ? (wonDeals.length / closedDeals.length * 100).toFixed(1) : 0, totalRevenue: wonDeals.reduce((sum, d) => sum + (d.attributes.amount || 0), 0), averageDealSize: wonDeals.length > 0 ? wonDeals.reduce((sum, d) => sum + (d.attributes.amount || 0), 0) / wonDeals.length : 0, averageSalesCycle: this.calculateAverageSalesCycle(wonDeals), loyaltyPointsAwarded: wonDeals.reduce( (sum, d) => sum + (d.attributes.loyalty_points_bonus || 0), 0 ) }; }
calculateAverageSalesCycle(wonDeals) { if (wonDeals.length === 0) return 0;
const totalDays = wonDeals.reduce((sum, deal) => { const created = new Date(deal.created_at); const closed = new Date(deal.attributes.stage_changed_at || deal.updated_at); return sum + Math.floor((closed - created) / (1000 * 60 * 60 * 24)); }, 0);
return Math.round(totalDays / wonDeals.length); }}API 方法参考
交易的增删改查操作
// Create a new dealconst deal = await dealsApi.createDeal({ name: 'New Enterprise Deal', attributes: { deal_stage: 'Lead', amount: 50000, pipeline: 'Enterprise Sales' }});
// Get deal by IDconst deal = await dealsApi.getDeal('deal_abc123def456');
// Update deal attributesawait dealsApi.updateDeal('deal_abc123def456', { attributes: { deal_stage: 'Negotiation', amount: 55000, probability: 80 }});
// Delete a dealawait dealsApi.deleteDeal('deal_abc123def456');
// List deals with filteringconst deals = await dealsApi.getDeals({ filters: { 'attributes.deal_stage': 'Qualified', 'attributes.amount': '>10000' }, sort: 'attributes.amount:desc', limit: 50});进阶查询
// Find deals closing this quarterconst quarterEnd = new Date();quarterEnd.setMonth(quarterEnd.getMonth() + 3);const closingDeals = await dealsApi.getDeals({ filters: { 'attributes.close_date': `<${quarterEnd.toISOString()}`, 'attributes.deal_stage': '!Closed Won,!Closed Lost' }});
// Find high-value stale deals (no update in 14 days)const staleDate = new Date(Date.now() - 14 * 24 * 60 * 60 * 1000);const staleDeals = await dealsApi.getDeals({ filters: { 'attributes.amount': '>25000', 'updated_at': `<${staleDate.toISOString()}`, 'attributes.deal_stage': '!Closed Won,!Closed Lost' }});
// Get deals by owner for performance reviewconst ownerDeals = await dealsApi.getDeals({ filters: { 'attributes.deal_stage': 'Closed Won' }});最佳实践
- 统一的阶段划分:清晰定义销售管道的各个阶段,并规定每个阶段应完成的动作
- 成交概率追踪:持续更新每笔交易的成交概率,让收入预测更加准确
- 及时更新:交易属性发生变化后尽快同步,保持销售管道视图的准确性
- 会员集成:把交易成交与会员积分发放关联起来,提升客户留存
- 自动化工作流:用阶段变更触发器自动创建后续的跟进任务
- 定期复盘管道:安排每周的销售管道复盘,及时找出停滞或有风险的交易
错误处理
try { const deal = await dealsApi.createDeal(dealData); console.log('Deal created:', deal.id);} catch (error) { if (error.status === 400) { console.error('Invalid deal data:', error.message); } else if (error.status === 404) { console.error('Associated company or contact not found'); } else if (error.status === 409) { console.error('Duplicate deal detected'); } else { console.error('Unexpected error:', error); }}