Skip to content

Workflow Automation with n8n and Make.com

Automation (n8n & Make)

By Elhabib Elhab · December 16, 2024 · 8 min read

Ask me about this on WhatsApp
Workflow Automation with n8n and Make.com

Project status: the workflows in this post are prototypes. They are example builds, not measured client deployments, so no results are reported.

In many small businesses the same details get copied by hand from a form or an inbox into a spreadsheet or CRM. Automation tools can take over those repeated steps, so the information moves on its own instead of being retyped.

In this post, I'll share my experience with two powerful automation platforms: n8n and Make.com (formerly Integromat), and the prototype workflows I've built with them for booking handling and lead follow-up.

Why Automation Matters

Before the technical details, here is what automation does and what it costs:

  • Time: repetitive steps run without someone doing them by hand
  • Fewer copying mistakes: data is moved between tools, not retyped
  • Volume: more requests can be handled without the same amount of manual work
  • Consistency: every request goes through the same steps
  • Cost: manual time is swapped for tool and hosting fees, which are worth comparing before you build

n8n vs Make.com: Choosing the Right Tool

n8n - The Open-Source Powerhouse

Best for:

  • Custom integrations and complex logic
  • Self-hosted solutions
  • Cost-conscious projects
  • Full control over data and processes
// Example n8n workflow for lead processing
{
  "nodes": [
    {
      "name": "Webhook Trigger",
      "type": "n8n-nodes-base.webhook",
      "parameters": {
        "path": "lead-webhook",
        "httpMethod": "POST"
      }
    },
    {
      "name": "Data Validation",
      "type": "n8n-nodes-base.function",
      "parameters": {
        "functionCode": `
          const data = $input.first().json;
          
          // Validate required fields
          if (!data.email || !data.name) {
            throw new Error('Missing required fields');
          }
          
          // Clean and format data
          return {
            email: data.email.toLowerCase().trim(),
            name: data.name.trim(),
            phone: data.phone ? data.phone.replace(/[^0-9]/g, '') : null,
            source: data.source || 'website',
            timestamp: new Date().toISOString()
          };
        `
      }
    },
    {
      "name": "CRM Integration",
      "type": "n8n-nodes-base.httpRequest",
      "parameters": {
        "url": "https://api.crm.com/contacts",
        "method": "POST",
        "headers": {
          "Authorization": "Bearer {{$credentials.crmApiKey}}",
          "Content-Type": "application/json"
        },
        "body": "={{$json}}"
      }
    }
  ]
}

Make.com - The Integration Specialist

Best for:

  • Quick setup and deployment
  • Extensive pre-built integrations
  • Non-technical users
  • Cloud-based solutions
{
  "scenario": {
    "name": "Booking Management Workflow",
    "modules": [
      {
        "name": "Booking Webhook",
        "type": "webhook",
        "url": "https://hook.eu1.make.com/booking-trigger"
      },
      {
        "name": "Data Processing",
        "type": "data-store",
        "operation": "create",
        "fields": {
          "booking_id": "{{1.booking_id}}",
          "customer_email": "{{1.customer_email}}",
          "check_in": "{{1.check_in_date}}",
          "check_out": "{{1.check_out_date}}",
          "status": "confirmed"
        }
      },
      {
        "name": "Send Confirmation Email",
        "type": "email",
        "to": "{{2.customer_email}}",
        "subject": "Booking Confirmation - {{2.booking_id}}",
        "body": "Your booking has been confirmed..."
      }
    ]
  }
}

Implementation Examples

1. Automated Lead Generation Pipeline

Problem: Leads that arrive by form or email are copied into the CRM by hand, so follow-up waits until someone has time Solution: Automated pipeline from lead capture to CRM integration

# Python script for complex data processing
import requests
import json
from datetime import datetime
 
class LeadProcessor:
    def __init__(self):
        self.crm_api = "https://api.crm.com"
        self.email_api = "https://api.email.com"
        self.analytics_api = "https://api.analytics.com"
    
    def process_lead(self, lead_data):
        # Step 1: Data enrichment
        enriched_data = self.enrich_lead_data(lead_data)
        
        # Step 2: Lead scoring
        score = self.calculate_lead_score(enriched_data)
        
        # Step 3: CRM integration
        crm_response = self.create_crm_contact(enriched_data, score)
        
        # Step 4: Automated follow-up
        if score > 70:
            self.schedule_immediate_followup(crm_response['contact_id'])
        else:
            self.schedule_nurture_sequence(crm_response['contact_id'])
        
        # Step 5: Analytics tracking
        self.track_lead_conversion(lead_data['source'], score)
        
        return crm_response
    
    def enrich_lead_data(self, lead):
        # Company information lookup
        company_info = self.get_company_data(lead['email'])
        
        # Social media profiles
        social_profiles = self.find_social_profiles(lead['email'])
        
        # Geographic data
        location_data = self.get_location_data(lead['ip_address'])
        
        return {
            **lead,
            'company': company_info,
            'social_profiles': social_profiles,
            'location': location_data,
            'enriched_at': datetime.now().isoformat()
        }

2. Content Generation Workflow

Problem: Creating consistent, high-quality content for multiple channels Solution: Automated content generation with AI integration

# n8n workflow configuration
workflow:
  name: "Content Generation Pipeline"
  nodes:
    - name: "Content Trigger"
      type: "schedule"
      parameters:
        cron: "0 9 * * 1"  # Every Monday at 9 AM
    
    - name: "Topic Research"
      type: "http-request"
      parameters:
        url: "https://api.content-research.com/trending"
        method: "GET"
    
    - name: "AI Content Generation"
      type: "openai"
      parameters:
        model: "gpt-4"
        prompt: |
          Create engaging content about: {{$json.topic}}
          Target audience: Real estate professionals
          Tone: Professional but approachable
          Length: 500-800 words
          Include: Practical tips and actionable advice
    
    - name: "Content Optimization"
      type: "function"
      parameters:
        code: |
          const content = $input.first().json;
          
          // SEO optimization
          const seoScore = calculateSEOScore(content);
          
          // Readability check
          const readabilityScore = calculateReadability(content);
          
          // Social media adaptation
          const socialMediaPosts = adaptForSocialMedia(content);
          
          return {
            original_content: content,
            seo_score: seoScore,
            readability_score: readabilityScore,
            social_posts: socialMediaPosts,
            optimized_content: optimizeContent(content)
          };
    
    - name: "Multi-Channel Publishing"
      type: "parallel"
      branches:
        - name: "Blog Post"
          type: "wordpress"
          parameters:
            title: "{{$json.optimized_content.title}}"
            content: "{{$json.optimized_content.body}}"
            status: "publish"
        
        - name: "Social Media"
          type: "social-media"
          parameters:
            platforms: ["linkedin", "twitter", "facebook"]
            posts: "{{$json.social_posts}}"
        
        - name: "Email Newsletter"
          type: "email-marketing"
          parameters:
            subject: "{{$json.optimized_content.title}}"
            content: "{{$json.optimized_content.body}}"
            list: "subscribers"

3. Booking Management System

Problem: Manual booking confirmations and follow-ups Solution: End-to-end booking automation

// Make.com scenario for booking management
const bookingWorkflow = {
  trigger: {
    type: "webhook",
    url: "https://hook.eu1.make.com/booking-webhook"
  },
  
  modules: [
    {
      name: "Validate Booking Data",
      type: "data-store",
      operation: "create",
      conditions: [
        {
          field: "email",
          operator: "is_not_empty"
        },
        {
          field: "check_in_date",
          operator: "is_not_empty"
        }
      ]
    },
    
    {
      name: "Check Availability",
      type: "http-request",
      url: "https://api.property-management.com/availability",
      method: "POST",
      body: {
        property_id: "{{1.property_id}}",
        check_in: "{{1.check_in_date}}",
        check_out: "{{1.check_out_date}}"
      }
    },
    
    {
      name: "Create Booking",
      type: "http-request",
      url: "https://api.booking-system.com/bookings",
      method: "POST",
      body: {
        customer: "{{1}}",
        property: "{{2.property}}",
        dates: "{{1.check_in_date}} to {{1.check_out_date}}",
        status: "confirmed"
      }
    },
    
    {
      name: "Send Confirmation",
      type: "email",
      to: "{{1.email}}",
      subject: "Booking Confirmation - {{3.booking_id}}",
      template: "booking-confirmation",
      variables: {
        booking_id: "{{3.booking_id}}",
        property_name: "{{3.property_name}}",
        check_in: "{{1.check_in_date}}",
        check_out: "{{1.check_out_date}}"
      }
    },
    
    {
      name: "Schedule Reminders",
      type: "schedule",
      delay: "7 days",
      action: "send_reminder",
      booking_id: "{{3.booking_id}}"
    }
  ]
};

Advanced Techniques and Best Practices

1. Error Handling and Monitoring

# Error handling in automation workflows
class WorkflowMonitor:
    def __init__(self):
        self.alert_system = AlertSystem()
        self.logger = WorkflowLogger()
    
    def handle_workflow_error(self, error, context):
        # Log the error
        self.logger.log_error(error, context)
        
        # Determine error severity
        severity = self.assess_error_severity(error)
        
        # Send appropriate alerts
        if severity == "critical":
            self.alert_system.send_immediate_alert(error, context)
        elif severity == "warning":
            self.alert_system.send_daily_summary(error, context)
        
        # Attempt recovery
        if self.can_recover(error):
            return self.attempt_recovery(error, context)
        
        return False
    
    def assess_error_severity(self, error):
        critical_errors = [
            "database_connection_failed",
            "payment_processing_failed",
            "email_delivery_failed"
        ]
        
        if any(critical in str(error).lower() for critical in critical_errors):
            return "critical"
        elif "timeout" in str(error).lower():
            return "warning"
        else:
            return "info"

2. Data Validation and Quality Control

// Data validation in n8n workflows
const validateData = (data) => {
  const errors = [];
  
  // Email validation
  if (!data.email || !isValidEmail(data.email)) {
    errors.push('Invalid email address');
  }
  
  // Phone validation
  if (data.phone && !isValidPhone(data.phone)) {
    errors.push('Invalid phone number');
  }
  
  // Date validation
  if (data.check_in_date && !isValidDate(data.check_in_date)) {
    errors.push('Invalid check-in date');
  }
  
  // Business logic validation
  if (data.check_in_date && data.check_out_date) {
    if (new Date(data.check_in_date) >= new Date(data.check_out_date)) {
      errors.push('Check-out date must be after check-in date');
    }
  }
  
  return {
    isValid: errors.length === 0,
    errors: errors,
    data: errors.length === 0 ? cleanData(data) : null
  };
};

3. Performance Optimization

# Caching and performance optimization
import redis
from functools import lru_cache
import asyncio
 
class WorkflowOptimizer:
    def __init__(self):
        self.redis_client = redis.Redis(host='localhost', port=6379, db=0)
        self.cache_ttl = 3600  # 1 hour
    
    @lru_cache(maxsize=1000)
    async def get_cached_data(self, key):
        # Check Redis cache first
        cached = self.redis_client.get(key)
        if cached:
            return json.loads(cached)
        
        # Fetch from source if not cached
        data = await self.fetch_from_source(key)
        
        # Cache the result
        self.redis_client.setex(key, self.cache_ttl, json.dumps(data))
        
        return data
    
    async def batch_process(self, items, batch_size=100):
        """Process items in batches for better performance"""
        results = []
        
        for i in range(0, len(items), batch_size):
            batch = items[i:i + batch_size]
            batch_results = await asyncio.gather(*[
                self.process_item(item) for item in batch
            ])
            results.extend(batch_results)
        
        return results

What These Workflows Change

These workflows are prototypes and have not been measured against a before/after baseline, so I'm not quoting any figures. Here is what the automation replaces:

  • Manual data entry: bookings and leads flow straight from the source (form, inbox, channel manager) into the CRM/sheet, instead of being retyped by hand
  • Response lag: workflows trigger the moment a lead or booking event arrives, rather than waiting for the next time someone checks the inbox
  • Process drift: every item passes through the same automated steps, so the process doesn't vary depending on who's handling it that day
  • Staff time: routine data-shuffling work is removed, freeing time for the parts of the job that actually need a person

Lessons Learned

Technical Insights:

  1. Start Simple: Begin with basic workflows and gradually add complexity
  2. Error Handling: Robust error handling is crucial for production systems
  3. Monitoring: Comprehensive logging and monitoring prevent issues
  4. Testing: Thorough testing of all workflow paths is essential

Business Insights:

  1. User Training: Proper training helps adoption
  2. Documentation: Clear documentation prevents confusion
  3. Iterative Improvement: Continuous optimization based on feedback
  4. Change Management: Gradual rollout reduces resistance

Future Enhancements

  1. AI Integration: Machine learning for predictive automation
  2. Advanced Analytics: Real-time insights and reporting
  3. Mobile Integration: Mobile-first workflow management
  4. API Expansion: More third-party integrations

Conclusion

Workflow automation with n8n and Make.com has transformed how I approach business process optimization. The key to success lies in:

  1. Understanding the Problem: Clearly define what needs to be automated
  2. Choosing the Right Tool: Match the tool to the use case
  3. Iterative Development: Start simple and add complexity gradually
  4. Continuous Monitoring: Track performance and optimize regularly

The combination of these platforms with thoughtful design can take repeated manual steps out of a business process.


Run a tour company, riad or local business? Send me your website or Google listing and I'll tell you, in plain language, where visitors hesitate and what I would fix first. Get my free website audit.

For real, delivered client work rather than prototypes, see case studies. Building something similar? See related services.

Free growth report

See what's costing you customers, and get the fixes

Paste your website. In about two minutes the report reads it, works out what you sell and who buys it, and hands you the exact fixes, your own AI assistant and a 90-day plan.

  • Free
  • About 2 minutes
  • No call needed

Built for any business

  • Restaurants & cafés
  • Clinics & dentists
  • Shops & online stores
  • Hotels & riads
  • Tours & activities
  • Salons & spas
  • Lawyers & accountants
  • Trades & home services