get_contact_tracking_logs
Retrieve event and tracking logs for a specific contact in ActiveCampaign. Filter by event type, date range, and paginate results for precise tracking data analysis.
Instructions
Busca os logs de eventos/tracking de um contato específico
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| contactId | Yes | ID do contato para buscar os logs de eventos | |
| dateRange | No | Filtrar por intervalo de datas | |
| eventType | No | Filtrar por tipo de evento específico (opcional) | |
| limit | No | Limite de resultados (padrão: 100, máximo: 100) | |
| offset | No | Offset para paginação (padrão: 0) |
Implementation Reference
- src/tools/tracking.ts:130-176 (handler)The primary handler function that executes the tool logic: fetches tracking logs via API for a specific contact ID with optional filters, formats the data, and returns it in MCP content format.private async getContactTrackingLogs( contactId: string, options: TrackingOptions = {} ) { try { console.error(`[DEBUG] Buscando tracking logs para contato ID: ${contactId}`); const params: any = { limit: options.limit || 100, offset: options.offset || 0, }; // Adicionar filtros opcionais if (options.eventType) { params.type = options.eventType; } if (options.dateRange?.start) { params.after = options.dateRange.start; } if (options.dateRange?.end) { params.before = options.dateRange.end; } const response = await this.apiClient.get( `/api/3/contacts/${contactId}/trackingLogs`, { params } ); const trackingData = await this.formatTrackingLogs(response.data); return { content: [ { type: 'text', text: JSON.stringify(trackingData, null, 2), }, ], }; } catch (error) { console.error(`[ERROR] Erro ao buscar tracking logs:`, error); throw new Error( `Erro ao buscar logs de tracking: ${error instanceof Error ? error.message : 'Erro desconhecido'}` ); } }
- src/tools/tracking.ts:11-70 (schema)Tool definition object including name, description, and detailed input schema with properties for contactId (required), limit, offset, eventType (enum), and dateRange.{ name: 'get_contact_tracking_logs', description: 'Busca os logs de eventos/tracking de um contato específico', inputSchema: { type: 'object', properties: { contactId: { type: 'string', description: 'ID do contato para buscar os logs de eventos', }, limit: { type: 'number', description: 'Limite de resultados (padrão: 100, máximo: 100)', default: 100, maximum: 100, }, offset: { type: 'number', description: 'Offset para paginação (padrão: 0)', default: 0, }, eventType: { type: 'string', description: 'Filtrar por tipo de evento específico (opcional)', enum: [ 'open', 'click', 'sent', 'bounce', 'unsubscribe', 'subscribe', 'reply', 'forward', 'update', 'deal_add', 'deal_update', 'deal_delete', 'note_add', 'task_add', 'automation_start', 'automation_complete' ] }, dateRange: { type: 'object', description: 'Filtrar por intervalo de datas', properties: { start: { type: 'string', description: 'Data de início (formato: YYYY-MM-DD)', }, end: { type: 'string', description: 'Data de fim (formato: YYYY-MM-DD)', }, }, }, }, required: ['contactId'], },
- src/index.ts:68-71 (registration)Registration in the main MCP server CallTool handler: checks if the tool name matches and dispatches to TrackingTools.executeTool.const trackingToolNames = ['get_contact_tracking_logs', 'get_contact_tracking_logs_by_email']; if (trackingToolNames.includes(name)) { return await this.trackingTools.executeTool(name, args); }
- src/index.ts:47-54 (registration)MCP ListTools handler registration that combines and returns tools from ContactTools and TrackingTools, including this tool's schema.this.server.setRequestHandler(ListToolsRequestSchema, async () => { const contactTools = this.contactTools.getTools(); const trackingTools = this.trackingTools.getTools(); return { tools: [...contactTools, ...trackingTools] as Tool[], }; });
- src/tools/tracking.ts:212-283 (helper)Helper function that processes raw API tracking logs: enriches with additional API calls for campaigns, formats timestamps, adds event descriptions, and creates summary.private async formatTrackingLogs(rawData: any): Promise<any> { const trackingLogs = rawData.trackingLogs || []; const meta = rawData.meta || {}; // Buscar informações adicionais para enriquecer os dados const enrichedLogs = await Promise.all( trackingLogs.map(async (log: any) => { const enrichedLog: any = { id: log.id, type: log.type, timestamp: log.tstamp, date: this.formatTimestamp(log.tstamp), contact: log.contact, subscriberId: log.subscriberid, hash: log.hash, description: this.getEventDescription(log.type), }; // Adicionar valor se existir if (log.value) { enrichedLog.value = log.value; } // Adicionar links se existirem if (log.links) { enrichedLog.links = log.links; } // Adicionar dados específicos baseados no tipo de evento (apenas se existirem) if (log.campaign) { try { const campaignResponse = await this.apiClient.get(`/api/3/campaigns/${log.campaign}`); enrichedLog.campaign = { id: log.campaign, name: campaignResponse.data.campaign?.name || 'N/A', }; } catch (error) { enrichedLog.campaign = { id: log.campaign, name: 'N/A' }; } } if (log.automation) { enrichedLog.automation = { id: log.automation }; } if (log.email) { enrichedLog.email = { id: log.email }; } if (log.link) { enrichedLog.link = { id: log.link }; } if (log.eventdata) { enrichedLog.eventData = log.eventdata; } return enrichedLog; }) ); return { summary: { total: meta.total || trackingLogs.length, count: meta.count || trackingLogs.length, limit: meta.limit || 100, offset: meta.offset || 0, eventTypes: this.getEventTypeSummary(trackingLogs), }, events: enrichedLogs, }; }