Skip to main content

Remove Tag Automation Processor

Overview

The Remove Tag automation removes CRM tags from deals when they enter a specific pipeline stage. It validates tag existence, prevents errors on already-removed tags, and tracks automation status.

Source File: queue-manager/queues/deals/automations/remove-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 Remove 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 Present
QUEUE->>DEAL: Remove tag from deal.tags[]
QUEUE->>DEAL: Mark automation triggered
else Tag Not Present
QUEUE->>DEAL: Skip (already removed)
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. Association Check: Skips deals not having the tag

Deal Eligibility

Same as Add Tag automation:

  • stage_id matches automation stage
  • automation_starts less than or equal to delayed date
  • automation_starts greater than or equal to automation creation date
  • Automation tracking checks

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();

// Remove tag from each deal
for (const deal of dealData) {
const tags = deal._doc.tags || [];
if (!tags.find(t => t.toString() === tag.toString())) {
throw new Error('Tag is already not associated.');
}
if (deal.tags) {
await Deal.updateOne({ _id: dealID }, { $pull: { tags: new mongoose.Types.ObjectId(tag) } });
}
}

Collections Used

Input: deal-automation

  • Automation configuration

Validation: crm-tag

  • Tag existence verification

Update: deal

  • Remove tag from deal.tags array using $pull
  • Update automation tracking fields

Use Cases

Example 1: Stage Progression

// Automation
{
stage_id: "closed_won",
action: "remove_tag",
data: { tag: "needs_follow_up" },
delay: 0
}

// Result: Remove follow-up tag when deal closes

Example 2: Cleanup on Rejection

// Automation
{
stage_id: "disqualified",
action: "remove_tag",
data: { tag: "qualified" },
delay: 0
}

// Result: Remove qualification tag when deal disqualified

Error Handling

Common Errors

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

Error Response

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

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: 164

💬

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