Loop Task¶
Overview¶
The Loop Task iterates through arrays or lists, executing subsequent tasks for each item. Use it to process multiple records, send bulk emails, update batches of data, or perform repetitive operations efficiently.
When to use this task:
- Process multiple database records
- Send personalized emails to multiple contacts
- Update multiple CRM records
- Sync batches of data to external systems
- Generate multiple documents or files
- Perform calculations on each array item
- Filter and process collections
Key Features:
- Iterate through JSON arrays
- Access current item data
- Break loop conditionally
- Track iteration count and index
- Nested loop support
- Process unlimited items (with pagination)
- Error handling per iteration
[SCREENSHOT NEEDED: Loop task configuration showing array source and iteration settings]
Quick Start¶
- Add Loop task to workflow
- Specify array to loop through
- Add tasks after Loop task
- Configure tasks to use loop item data
- Test with small dataset
- Save
Simple Example:
Configuring the Loop¶
Array Source¶
Specify which array to loop through:
From MySQL Query:
From Webhook In:
From Code Task:
Static Array (for testing):
Loop Output Fields¶
For each iteration, the Loop task provides:
| Field | Description | Example |
|---|---|---|
task_[ID]_current_index | Current iteration number (0-based) | 0, 1, 2 |
task_[ID]_item_[field] | Field from current item | task_29001_email |
task_[ID]_total_items | Total items in array | 25 |
task_[ID]_is_first | True if first iteration | true / false |
task_[ID]_is_last | True if last iteration | true / false |
Accessing Loop Data¶
Current item fields:
Loop metadata:
Current iteration: {{task_29001_current_index}}
Total items: {{task_29001_total_items}}
Is this first item? {{task_29001_is_first}}
Is this last item? {{task_29001_is_last}}
Tasks Inside Loop¶
Email Each Contact¶
1. MySQL Query - Get contacts needing follow-up
2. Loop - For each contact
3. Email - Send to {{task_29001_email}}
Subject: Hi {{task_29001_first_name}}!
Body: Personalized content for {{task_29001_name}}
Update Multiple Records¶
1. Webhook In - Receive batch update
2. Loop - For each record
3. Match to Client - Find contact by {{task_29001_email}}
4. Edit Client - Update fields with loop data
API Sync with Rate Limiting¶
1. MySQL Query - Get unsync records
2. Loop - For each record
3. Webhook Out - Sync {{task_29001_id}} to external API
4. Delay - Wait 1 second (rate limiting)
5. MySQL Query - Mark {{task_29001_id}} as synced
Conditional Processing¶
1. Loop - For each item
2. If Task - Check {{task_29001_status}} = "active"
True: Process active items
False: Skip inactive items
Loop Control¶
Break Loop Early¶
Stop loop based on condition:
Configuration:
Use case: Stop processing if error occurs.
Max Iterations¶
Limit loop iterations:
Configuration:
Use case: Prevent runaway loops, test with subset.
Skip Empty Items¶
Configuration:
Use case: Only process valid records.
Real-World Examples¶
Example 1: Daily Follow-Up Emails¶
Workflow: 1. Timer Trigger - Every day at 9 AM 2. MySQL Query - Get contacts needing follow-up 3. Loop - Process each contact 4. Email - Send personalized email 5. Edit Client - Log follow-up sent
MySQL Query:
SELECT id, email, first_name, last_name, custom_last_contact
FROM contacts
WHERE custom_follow_up_date = CURDATE()
AND custom_follow_up_sent = 0
LIMIT 50
Loop Configuration:
Email Task:
To: {{task_29001_email}}
Subject: Following up, {{task_29001_first_name}}
Hi {{task_29001_first_name}},
I wanted to follow up on our conversation...
Best regards
Edit Client:
Contact ID: {{task_29001_id}}
Update: custom_follow_up_sent = 1
Update: custom_last_email_date = {{task_48001_current_date}}
Example 2: Bulk Data Sync¶
Workflow: 1. Timer Trigger - Every hour 2. MySQL Query - Get updated records 3. Loop - Process each record 4. Webhook Out - Sync to external CRM 5. If Task - Check if successful 6. MySQL Query - Update sync status
MySQL Query:
Loop through results
Webhook Out:
Method: POST
URL: https://external-crm.com/api/contacts
Body:
{
"email": "{{task_29001_email}}",
"name": "{{task_29001_name}}",
"phone": "{{task_29001_phone}}",
"external_id": "{{task_29001_id}}"
}
If Successful (check response code = 200):
Delay 0.5 seconds between iterations (rate limiting)
Example 3: Multi-Recipient Notification¶
Workflow: 1. CRM Trigger - Hot lead created 2. MySQL Query - Get sales team members 3. Loop - Notify each team member
MySQL Query:
Loop through team members
Email:
To: {{task_29001_email}}
Subject: New hot lead assigned!
Hi {{task_29001_first_name}},
A new hot lead just came in:
- Name: {{task_47001_full_name}}
- Email: {{task_47001_email}}
- Score: {{task_47001_custom_lead_score}}
View in CRM: https://app.basecloud.com/contacts/{{task_47001_contact_id}}
Example 4: Order Items Processing¶
Workflow: 1. Webhook In - Order received 2. Code Task - Parse order items 3. Loop - Process each item 4. MySQL Query - Update inventory
Code Task:
const order = JSON.parse(input.task_46001_body);
return {
items: JSON.stringify(order.items || [])
};
Loop Configuration:
MySQL Query (in loop):
Parameters:{{task_29001_quantity}}, {{task_29001_product_id}} After loop: 5. Email - Send order confirmation with all items
Example 5: Conditional Batch Operations¶
Workflow: 1. Timer Trigger - Weekly cleanup 2. MySQL Query - Get inactive contacts 3. Loop - Check each contact 4. If Task - Determine action 5a. Edit Client - Archive contact (if > 180 days) 5b. Email - Re-engagement campaign (if 90-180 days)
MySQL Query:
SELECT id, email, first_name, custom_last_activity
FROM contacts
WHERE custom_last_activity < DATE_SUB(NOW(), INTERVAL 90 DAY)
LIMIT 200
Loop through contacts
Code Task (calculate days inactive):
const lastActivity = new Date(input.task_29001_custom_last_activity);
const today = new Date();
const daysInactive = Math.floor((today - lastActivity) / (1000*60*60*24));
return {
days_inactive: daysInactive,
should_archive: daysInactive > 180,
should_reengage: daysInactive >= 90 && daysInactive <= 180
};
If Task 1: Check {{task_42001_should_archive}} = true - True: Edit Client → Add "Archived" tag, Status = "Inactive"
If Task 2: Check {{task_42001_should_reengage}} = true - True: Email → Send re-engagement campaign
Nested Loops¶
Loop within a loop for complex processing.
Example: Process orders and their items:
1. MySQL Query - Get orders
2. Loop (Outer) - For each order
3. MySQL Query - Get items for {{task_29001_order_id}}
4. Loop (Inner) - For each item
5. Process item: {{task_29002_item_name}}
Access nested loop data:
Note: Nested loops consume more execution time and resources.
Best Practices¶
Performance¶
- Limit iterations - Process in batches (100-500 per run)
- Add delays - Rate limit API calls (0.5-1 second)
- Paginate large datasets - Multiple scheduled runs
- Filter before looping - Use SQL WHERE to reduce items
- Break early - Stop loop when condition met
Error Handling¶
- Try-catch in Code tasks - Handle errors per iteration
- Check success - Verify operations completed
- Log failures - Track which items failed
- Continue on error - Don't stop entire loop for one failure
- Retry logic - Re-process failed items later
Data Quality¶
- Validate before loop - Check array exists and isn't empty
- Handle missing fields - Provide defaults
- Check null values - Skip invalid items
- Deduplicate - Ensure unique items
- Sort order - Process in logical sequence
Maintainability¶
- Name loops clearly - "Loop through customers" not "Loop 1"
- Comment complex logic - Explain iteration purpose
- Keep simple - Max 5-10 tasks in loop
- Extract complex operations - Use Code task for calculations
- Test with small dataset - Verify logic before production
Troubleshooting¶
Loop Not Executing¶
Check: 1. Array field exists? {{task_x_results_JSON}} 2. Array empty? Check {{task_x_rows}} > 0 3. Valid JSON format? 4. Loop task enabled?
Debug:
Can't Access Loop Item Data¶
Error: {{task_29001_email}} is empty
Check: 1. Field name correct? Case-sensitive 2. Loop task ID correct? 3. Task is inside loop (after Loop task)? 4. Array items have that field?
Debug: View execution history → Loop task → See item structure
Loop Running Too Long¶
Causes: - Too many items (1000s) - No delay between iterations - Slow external API calls - Complex tasks in loop
Solutions: - Add Max Iterations: 100 - Add Delay task in loop - Process in batches - Optimize tasks
Loop Stuck on One Item¶
Check: - Infinite nested loop? - Task failing but not stopping? - Break condition never met?
Solution: - Add Max Iterations safety limit - Check task execution in history - Verify break conditions
Memory/Timeout Issues¶
Error: Workflow timeout or Memory limit
Causes: - Processing thousands of items - Large data in each iteration - Complex calculations
Solutions: - Reduce batch size - Paginate: Process 100 per run, multiple runs - Simplify tasks in loop - Use database queries instead of loading all data
Frequently Asked Questions¶
What's the maximum loop iterations?¶
No hard limit, but practical limits: - Recommended: 100-500 per workflow run - Maximum: 1000s possible but slower - Best practice: Batch process with multiple scheduled runs
Can I loop through a CSV?¶
Yes, first parse CSV to JSON array using Code task, then loop through result.
How do I count successful vs failed iterations?¶
Use Variable task to track:
let success = parseInt(input.task_41001_success_count) || 0;
if (input.task_x_success) success++;
return { success_count: success };
Can I loop through non-JSON data?¶
Loop requires JSON array format. Use Code task to convert other formats first.
How do I stop loop midway?¶
Set break condition:
Can I restart failed loop iterations?¶
Not automatically. Best practice: 1. Log failed items to database 2. Create separate workflow to retry failures
Do all tasks in loop run for each item?¶
Yes, unless you use If tasks for conditional execution.
Can I modify loop array while looping?¶
No, loop operates on snapshot of array at start.
Related Tasks¶
- MySQL Query - Provide arrays to loop through
- Code Task - Transform data before/in loop
- If Task - Conditional logic per iteration
- Delay Task - Rate limiting in loops
- Variable Task - Track loop progress