Skip to main content

Add Tag Automation Processor

Overview

The Add Tag automation adds CRM tags to deals when they enter a specific pipeline stage. It validates tag existence, prevents duplicates, and tracks automation status with retry logic.

Source File: queue-manager/queues/deals/automations/add-tag.js
Triggered By: queue-manager/services/deals/automations.js
Business Impact: MEDIUM - Deal organization

Processing Logic

sequenceDiagram
participant AUTO as Automation Service
participant QUEUE as Add Tag Queue
participant DEAL as Deals Collection
participant TAG as CRM Tags

AUTO->>QUEUE: Add automation job
QUEUE->>TAG: Validate tag exists
TAG-->>QUEUE: Tag valid

QUEUE->>DEAL: Find eligible deals<br/>(stage + time window)

loop For Each Deal
QUEUE->>DEAL: Check if tag exists
alt Tag Not Present
QUEUE->>DEAL: Add tag to deal.tags[]
QUEUE->>DEAL: Mark automation triggered
else Tag Exists
QUEUE->>DEAL: Skip (already tagged)
end
end

QUEUE->>AUTO: Update automation status

Key Features

Validation

  1. Tag ID Validation: Checks if tag is valid ObjectId
  2. Tag Existence: Verifies tag exists in account
  3. Duplicate Prevention: Skips deals already having the tag

Deal Eligibility

Deals must meet ALL criteria:

  • stage_id matches automation stage
  • automation_starts less than or equal to delayed date (now - delay)
  • automation_starts greater than or equal to automation creation date
  • NOT in skip_automations array
  • NOT in automation_triggered array
  • OR in retry_automations array

Delayed Execution

const delayedDate = moment().subtract(automation.delay, 'seconds');

Allows configurable delay after deal enters stage.

Core Code Pattern

// Validate tag
if (!tag || !mongoose.Types.ObjectId.isValid(tag)) {
throw new Error('Invalid tag id provided');
}

const validTag = await CrmTag.countDocuments({ _id: tag, account: accountID });
if (!validTag) {
throw new Error('Tag not found.');
}

// Find eligible deals
let dealData = await Deal.find({
stage_id: automation.stage_id,
$and: [
{ automation_starts: { $lte: delayedDate.toDate() } },
{ automation_starts: { $gte: automation.createdAt } },
],
$or: [
{ retry_automations: automationId },
{
$and: [
{ skip_automations: { $ne: automationId } },
{ automation_triggered: { $ne: automationId } },
],
},
],
}).exec();

// Add tag to each deal
for (const deal of dealData) {
const tags = deal._doc.tags || [];
if (tags.find(t => t.toString() === tag.toString())) {
throw new Error('Tag already associated.');
}
if (deal.tags) {
deal.tags.push(new mongoose.Types.ObjectId(tag));
} else {
deal.tags = [new mongoose.Types.ObjectId(tag)];
}
await deal.save();
}

Collections Used

Input: deal-automation

  • Automation configuration

Validation: crm-tag

  • Tag existence verification

Update: deal

  • Add tag to deal.tags array
  • Update automation tracking fields

Automation Tracking

Success Tracking

{
automation_triggered: [automationId],
retry_automations: [], // Removed after success
skip_automations: [] // Not added
}

Failure Tracking

{
retry_automations: [automationId], // Added on failure for retry
skip_automations: [], // Can be manually added to skip
automation_triggered: [] // Not added until success
}

Error Handling

Common Errors

  1. Invalid Tag ID: Not a valid ObjectId
  2. Tag Not Found: Tag doesn't exist in account
  3. Tag Already Associated: Deal already has this tag
  4. Deal Not Found: Deal was deleted

Error Response

{
deal: dealID,
tag_id: ObjectId,
message: "Tag already associated.",
additional_info: {...}
}

Use Cases

Example 1: Lead Qualification

// Automation
{
stage_id: "hot_leads",
action: "add_tag",
data: { tag: "qualified" },
delay: 0
}

// Result: All deals in "hot_leads" stage get "qualified" tag

Example 2: Delayed Tagging

// Automation
{
stage_id: "new_lead",
action: "add_tag",
data: { tag: "needs_follow_up" },
delay: 86400 // 24 hours
}

// Result: Tag added 24 hours after deal enters stage

Performance

Execution Time: 100-500ms per automation
Batch Size: All eligible deals in one run
Retry Strategy: 3 attempts with exponential backoff


Complexity: LOW
Lines of Code: 163

💬

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:31 AM