Auto Response Rules Controller
Source: internal/api/v1/reviews/controllers/auto-response-rules.js
Service: autoResponseRules service
Module: Reviews
Overview
The Auto Response Rules controller manages automated response rules that trigger based on review conditions (rating, platform, keywords). It enables businesses to automatically respond to reviews matching specific criteria, improving response time and consistency.
Key Capabilities
- Create Automated Rules with condition-based triggers
- List All Rules with pagination
- Update Rules for active/inactive state and conditions
- Delete Rules when no longer needed
- Duplicate Rules for easy template creation
- Condition Matching on rating, platform, keywords
MongoDB Collections
| Collection | Operations | Purpose |
|---|---|---|
review-auto-response-rules | CREATE, READ, UPDATE, DELETE | Store automation rules |
Service Methods
1. create()
Create a new auto-response rule with conditions and response template.
Endpoint: POST /reviews/auto-response-rules
Controller Logic:
exports.create = catchAsync(async (req, res) => {
const account_id = req.auth.account_id;
const user_id = req.auth.uid;
const { name, active, conditions } = req.body;
const data = await autoResponseRules.create({ account_id, user_id, name, active, conditions });
res.json({
success: true,
data,
});
});
Request:
POST /api/v1/v1/reviews/auto-response-rules
Content-Type: application/json
{
"name": "Positive Review Auto-Response",
"active": true,
"conditions": {
"rating": { "operator": "gte", "value": 4 },
"platforms": ["google", "facebook"],
"response_template": "Thank you for your positive feedback! We're thrilled you had a great experience."
}
}
Request Body:
{
name: string; // Rule name for identification
active: boolean; // Whether rule is active
conditions: {
rating?: { // Rating condition (optional)
operator: 'eq' | 'gte' | 'lte' | 'gt' | 'lt';
value: 1 | 2 | 3 | 4 | 5;
};
platforms?: string[]; // Platforms to match (google, facebook, yelp, etc.)
keywords?: { // Keyword matching (optional)
include?: string[]; // Review must contain these
exclude?: string[]; // Review must not contain these
};
response_template: string; // Response text with variables
delay_minutes?: number; // Optional delay before sending
};
}
Response:
{
"success": true,
"data": {
"_id": "rule_abc123",
"account_id": "acc_123",
"user_id": "user_456",
"name": "Positive Review Auto-Response",
"active": true,
"conditions": {
"rating": { "operator": "gte", "value": 4 },
"platforms": ["google", "facebook"],
"response_template": "Thank you for your positive feedback!"
},
"created_at": "2024-12-08T10:00:00Z",
"updated_at": "2024-12-08T10:00:00Z"
}
}
Business Logic:
graph TD
A[Receive Create Request] --> B[Extract Auth Context]
B --> C[Validate Request Body]
C --> D{Valid Conditions?}
D -->|No| E[Return 400 Error]
D -->|Yes| F[Call autoResponseRules.create]
F --> G[Create Rule Document]
G --> H[Set account_id + user_id]
H --> I[Validate Rating Range]
I --> J[Validate Platform List]
J --> K[Save to MongoDB]
K --> L[Return Created Rule]
L --> M[Send Response]
Condition Examples:
- High Rating Response:
{
"rating": { "operator": "gte", "value": 4 },
"response_template": "Thank you {{author_name}}! We're glad you enjoyed our service."
}
- Low Rating Alert:
{
"rating": { "operator": "lte", "value": 2 },
"response_template": "We're sorry to hear about your experience. Please contact us at support@example.com"
}
- Platform-Specific:
{
"platforms": ["google"],
"response_template": "Thanks for your Google review!"
}
- Keyword Triggered:
{
"keywords": {
"include": ["staff", "helpful"],
"exclude": ["slow", "rude"]
},
"response_template": "We're happy our staff was helpful!"
}
2. list()
Retrieve all auto-response rules with pagination.
Endpoint: GET /reviews/auto-response-rules
Controller Logic:
exports.list = catchAsync(async (req, res) => {
const account_id = req.auth.account_id;
const { page, limit } = req.query;
const { data, paginate } = await autoResponseRules.list({ account_id, page, limit });
res.json({
success: true,
data,
pagination: paginate,
});
});
Request:
GET /api/v1/v1/reviews/auto-response-rules?page=1&limit=20
Query Parameters:
page(number, optional) - Page number (default: 1)limit(number, optional) - Items per page (default: 20)
Response:
{
"success": true,
"data": [
{
"_id": "rule_abc123",
"name": "Positive Review Auto-Response",
"active": true,
"conditions": { "rating": { "operator": "gte", "value": 4 } },
"created_at": "2024-12-08T10:00:00Z",
"updated_at": "2024-12-08T10:00:00Z",
"usage_count": 45
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 5,
"pages": 1
}
}
3. get()
Retrieve a single auto-response rule by ID.
Endpoint: GET /reviews/auto-response-rules/:id
Controller Logic:
exports.get = catchAsync(async (req, res) => {
const account_id = req.auth.account_id;
const { id } = req.params;
const data = await autoResponseRules.get(id, account_id);
res.json({
success: true,
data,
});
});
Request:
GET / api / v1 / a / reviews / auto - response - rules / rule_abc123;
Response:
{
"success": true,
"data": {
"_id": "rule_abc123",
"account_id": "acc_123",
"user_id": "user_456",
"name": "Positive Review Auto-Response",
"active": true,
"conditions": {
"rating": { "operator": "gte", "value": 4 },
"platforms": ["google", "facebook"],
"response_template": "Thank you {{author_name}}!",
"delay_minutes": 0
},
"created_at": "2024-12-08T10:00:00Z",
"updated_at": "2024-12-08T10:00:00Z",
"usage_count": 45,
"last_triggered": "2024-12-08T15:30:00Z"
}
}
Business Logic:
graph TD
A[Receive Get Request] --> B[Extract Rule ID]
B --> C[Extract account_id]
C --> D[Call autoResponseRules.get]
D --> E{Rule Exists?}
E -->|No| F[Throw 404 Not Found]
E -->|Yes| G{Belongs to Account?}
G -->|No| H[Throw 404 Not Found]
G -->|Yes| I[Return Rule Data]
I --> J[Send Response]
4. update()
Update an existing auto-response rule.
Endpoint: PUT /reviews/auto-response-rules/:id
Controller Logic:
exports.update = catchAsync(async (req, res) => {
const account_id = req.auth.account_id;
const { id } = req.params;
const { name, active, conditions } = req.body;
const data = await autoResponseRules.update({ id, account_id, name, active, conditions });
res.json({
success: true,
data,
});
});
Request:
PUT /api/v1/v1/reviews/auto-response-rules/rule_abc123
Content-Type: application/json
{
"name": "Updated Rule Name",
"active": false,
"conditions": {
"rating": { "operator": "gte", "value": 5 },
"response_template": "Thank you for the 5-star review!"
}
}
Response:
{
"success": true,
"data": {
"_id": "rule_abc123",
"name": "Updated Rule Name",
"active": false,
"conditions": {
"rating": { "operator": "gte", "value": 5 },
"response_template": "Thank you for the 5-star review!"
},
"updated_at": "2024-12-08T16:00:00Z"
}
}
Use Cases:
- Pause Rule: Set
active: falseto temporarily disable - Update Response: Change template text
- Adjust Conditions: Modify rating threshold or platforms
- Add Delay: Include
delay_minutesfor strategic timing
5. delete()
Delete an auto-response rule.
Endpoint: DELETE /reviews/auto-response-rules/:id
Controller Logic:
exports.delete = catchAsync(async (req, res) => {
const account_id = req.auth.account_id;
const { id } = req.params;
await autoResponseRules.delete(id, account_id);
res.json({
success: true,
message: 'Deleted successfully',
});
});
Request:
DELETE / api / v1 / a / reviews / auto - response - rules / rule_abc123;
Response:
{
"success": true,
"message": "Deleted successfully"
}
Business Logic:
graph TD
A[Receive Delete Request] --> B[Extract Rule ID]
B --> C[Extract account_id]
C --> D[Call autoResponseRules.delete]
D --> E{Rule Exists?}
E -->|No| F[Throw 404 Not Found]
E -->|Yes| G{Belongs to Account?}
G -->|No| H[Throw 404 Not Found]
G -->|Yes| I[Delete from MongoDB]
I --> J[Send Success Response]
Important Notes:
- ⚠️ Deletion is permanent (no soft delete shown)
- ⚠️ Historical responses remain intact
- ✅ Cannot delete rules from other accounts
6. duplicate()
Duplicate an existing rule to create a new one with same conditions.
Endpoint: POST /reviews/auto-response-rules/:id/duplicate
Controller Logic:
exports.duplicate = catchAsync(async (req, res) => {
const account_id = req.auth.account_id;
const user_id = req.auth.uid;
const { id } = req.params;
const data = await autoResponseRules.duplicate(id, account_id, user_id);
res.json({
success: true,
data,
});
});
Request:
POST / api / v1 / a / reviews / auto - response - rules / rule_abc123 / duplicate;
Response:
{
"success": true,
"data": {
"_id": "rule_xyz789",
"name": "Positive Review Auto-Response (Copy)",
"active": false,
"conditions": {
"rating": { "operator": "gte", "value": 4 },
"response_template": "Thank you!"
},
"created_at": "2024-12-08T17:00:00Z"
}
}
Business Logic:
graph TD
A[Receive Duplicate Request] --> B[Extract Source Rule ID]
B --> C[Call autoResponseRules.duplicate]
C --> D[Fetch Source Rule]
D --> E{Rule Exists?}
E -->|No| F[Throw 404 Not Found]
E -->|Yes| G[Clone Rule Data]
G --> H[Append Copy to Name]
H --> I[Set active: false]
I --> J[Assign New ID]
J --> K[Save to MongoDB]
K --> L[Return New Rule]
L --> M[Send Response]
Key Features:
- Safe Duplication: New rule starts as inactive
- Name Suffix: Adds " (Copy)" to distinguish
- Same Conditions: Preserves all condition logic
- Template Creation: Easy way to create similar rules
Use Cases:
- Create similar rules for different platforms
- A/B test different response templates
- Create backup before modifying existing rule
Request/Response Flow
Complete Auto-Response Rule Flow
sequenceDiagram
participant Client
participant Controller
participant Service
participant MongoDB
participant ReviewWebhook
Note over Client,ReviewWebhook: Rule Creation
Client->>Controller: POST /auto-response-rules
Controller->>Service: create(account_id, name, conditions)
Service->>MongoDB: Insert rule document
MongoDB-->>Service: Created rule
Service-->>Controller: Rule data
Controller-->>Client: Success response
Note over Client,ReviewWebhook: New Review Arrives
ReviewWebhook->>Service: New review event
Service->>MongoDB: Find active rules for account
MongoDB-->>Service: Matching rules
Service->>Service: Evaluate conditions
Service->>Service: Check rating match
Service->>Service: Check platform match
Service->>Service: Check keyword match
Service->>MongoDB: Create automated response
Service->>MongoDB: Increment rule.usage_count
Note over Client,ReviewWebhook: Rule Management
Client->>Controller: PUT /auto-response-rules/:id
Controller->>Service: update(id, active: false)
Service->>MongoDB: Update rule
MongoDB-->>Service: Updated rule
Service-->>Controller: Updated data
Controller-->>Client: Success response
Edge Cases & Error Handling
Common Scenarios
1. Invalid Rating Operator:
// Validation catches invalid operators
{
"rating": {
"operator": "invalid", // Must be: eq, gte, lte, gt, lt
"value": 4
}
}
// Returns 400 Bad Request
2. Rating Out of Range:
// Rating must be 1-5
{
"rating": { "operator": "eq", "value": 6 } // Invalid
}
// Returns 400 Bad Request
3. Duplicate Rule Not Found:
// If source rule doesn't exist
POST / auto - response - rules / invalid_id / duplicate;
// Returns 404 Not Found
4. Conflicting Rules:
// Multiple rules can match same review
// Service layer handles priority:
// 1. Most specific conditions first
// 2. Created date (newest first)
// 3. Only first match triggers
5. Inactive Rule:
// Rules with active: false never trigger
// But remain in database for reactivation
const activeRules = await Rule.find({ account_id, active: true });
6. Template Variable Missing:
// If template uses {{author_name}} but review has no author
// Service layer handles gracefully:
"Thank you {{author_name}}!" → "Thank you !"
// Or uses default: "Thank you Valued Customer!"
Authorization
Authentication: Required (JWT Bearer token)
Authorization Rules:
- ✅ Account-scoped: All operations filtered by
account_id - ✅ User tracking: Creator tracked via
user_id - ❌ No cross-account access
- ❌ Cannot modify other accounts' rules
Multi-Tenant Pattern:
// Every operation scoped to account
const account_id = req.auth.account_id;
// Service layer enforces ownership
await Rule.findOne({ _id: id, account_id });
Integration Points
Related Controllers
Dependencies:
- Reviews Controller: Rules trigger on review events
- Response Templates Controller: Can reference template IDs
- Config Controller: Requires platform connections
Triggered By:
- Webhook Controller: New review webhooks trigger evaluation
- Platform Sync Jobs: Background sync triggers rules
Triggers:
- Notification Service: Sends responses to platforms
- Activity Log: Records automated responses
Important Notes
Rule Evaluation Logic
-
Condition Matching:
- ALL conditions must match (AND logic)
- Rating: Operator determines match (
>=,==,<=) - Platform: Must be in platforms array
- Keywords: ALL include must exist, NONE exclude can exist
-
Priority System:
- More specific rules (more conditions) evaluated first
- Newest rules take precedence over older
- Only one rule triggers per review
-
Response Timing:
delay_minutes: 0= immediatedelay_minutes: 60= 1 hour delay- Useful for appearing "human"
Performance Considerations
- Rule Evaluation: O(n) where n = active rules count
- Caching: Active rules cached for 5 minutes
- Batch Processing: Reviews processed in batches
- Indexing:
account_id+activeshould be compound index
Template Variables
Supported variables in response templates:
{{author_name}}- Review author's name{{rating}}- Star rating (1-5){{platform}}- Platform name{{business_name}}- Account business name{{review_date}}- Review creation date
Related Documentation
- Reviews Controller (link removed - file does not exist) - Review management
- Response Templates Controller - Reusable templates
- Webhooks Controller - Review event triggers
- Config Controller - Platform setup
Version: 1.0
Last Updated: December 2024
Status: ✅ Production Ready