DEV Community

Hackceleration
Hackceleration

Posted on • Originally published at hackceleration.com

Building a Lead Capture Form with n8n, Notion, and Slack

Building a Lead Capture Form with n8n, Notion, and Slack

You need to capture leads from your website and get them into your database while notifying your team. Here's how to architect this integration in n8n using its Form Trigger, Notion API, and Slack API.

Architecture Overview

This workflow uses three components in a parallel execution pattern:

[Form Submission]
       |
       v
[n8n Form Trigger] --> [Notion API: Create Database Entry]
                   |
                   --> [Slack API: Send Channel Message]
Enter fullscreen mode Exit fullscreen mode

Why this architecture? The parallel execution of Notion and Slack nodes ensures both actions happen simultaneously—database entry and team notification occur in under a second. n8n's Form Trigger eliminates the need for external form builders like Typeform or Google Forms, giving you full control over the data flow from submission to storage.

Alternatives considered:

  • Webhooks from external form builders (adds unnecessary third-party dependency)
  • Sequential execution (Notion then Slack) would add latency
  • Email-based notifications (less immediate, harder to track)

API Integration Deep-Dive

n8n Form Trigger Configuration

The Form Trigger creates an HTTP endpoint that serves an HTML form and captures submissions.

Authentication: None (public form)

Form Element Structure:

// Form fields configuration
{
  "FirstName": { type: "text", required: true },
  "LastName": { type: "text", required: true },
  "Email": { type: "email", required: true }
}
Enter fullscreen mode Exit fullscreen mode

Response Structure:

{
  "FirstName": "John",
  "LastName": "Doe",
  "Email": "john@example.com",
  "submittedAt": "ISO-8601-timestamp"
}
Enter fullscreen mode Exit fullscreen mode

Critical Parameters:

  • Form URL Mode: Toggle between Test URL (development) and Production URL (live deployment)
  • The production URL format: https://your-n8n-instance.com/form/[workflow-id]
  • Embed using iframe: <iframe src="production-url" width="100%" height="600px"></iframe>

Gotchas:

  • Production URL only becomes available after first workflow save and activation
  • Form styling is limited—use iframe CSS for customization
  • No built-in CAPTCHA—implement rate limiting or use n8n's HTTP Request node with external CAPTCHA validation if needed

Notion API Integration

Authentication: OAuth 2.0 via Internal Integration

Get credentials:

  1. Visit https://www.notion.so/my-integrations
  2. Create new integration
  3. Copy the Internal Integration Token
  4. Share your target database with the integration

API Request Structure:

// n8n handles this internally, but here's the equivalent cURL
POST https://api.notion.com/v1/pages
Headers: {
  "Authorization": "Bearer secret_[your-token]",
  "Notion-Version": "2022-06-28",
  "Content-Type": "application/json"
}
Body: {
  "parent": { "database_id": "your-database-id" },
  "properties": {
    "Email": { "email": "john@example.com" },
    "firstname": { "rich_text": [{ "text": { "content": "John" } }] }
  }
}
Enter fullscreen mode Exit fullscreen mode

Response Structure:

{
  "object": "page",
  "id": "page-id",
  "created_time": "timestamp",
  "properties": { /* property values */ }
}
Enter fullscreen mode Exit fullscreen mode

Property Mapping in n8n:

  • Use expressions: {{ $json.Email }} to reference form data
  • Property names are case-sensitive: "Email" ≠ "email"
  • Notion database must have matching property types (email property for email, text for names)

Rate Limits:

  • 3 requests per second per integration
  • Handle 429 responses with exponential backoff

Common Errors:

  • 400: Property type mismatch (e.g., sending text to email property)
  • 404: Database not shared with integration
  • 401: Invalid or expired token

Slack API Integration

Authentication: OAuth 2.0 (Bot Token)

Required scopes:

  • chat:write (send messages)
  • channels:read (list channels)

Get credentials:

  1. Visit https://api.slack.com/apps
  2. Create new app
  3. Install to workspace
  4. Copy Bot User OAuth Token

API Request Structure:

POST https://slack.com/api/chat.postMessage
Headers: {
  "Authorization": "Bearer xoxb-your-bot-token",
  "Content-Type": "application/json"
}
Body: {
  "channel": "C1234567890",
  "text": "New lead: John Doe - john@example.com"
}
Enter fullscreen mode Exit fullscreen mode

Response Structure:

{
  "ok": true,
  "channel": "C1234567890",
  "ts": "1234567890.123456",
  "message": { /* message details */ }
}
Enter fullscreen mode Exit fullscreen mode

Dynamic Message Construction in n8n:

// Using n8n expression syntax
`New lead: {{ $('Lead Capture Form').item.json.FirstName }} {{ $('Lead Capture Form').item.json.LastName }} - {{ $('Lead Capture Form').item.json.Email }}`
Enter fullscreen mode Exit fullscreen mode

Rate Limits:

  • Tier 3: 50+ requests per minute
  • Handle rate limit headers: Retry-After

Common Errors:

  • not_in_channel: Bot not invited to target channel
  • channel_not_found: Invalid channel ID
  • invalid_auth: Expired or invalid token

Implementation Gotchas

Handling Missing Data:

  • n8n expressions return empty string for missing fields
  • Add validation in Form Trigger (mark fields as required)
  • Use Set node before Notion/Slack to provide defaults:
{{ $json.FirstName || 'Unknown' }}
Enter fullscreen mode Exit fullscreen mode

Parallel Execution Failures:

  • If Notion fails, Slack still executes (no rollback by default)
  • Add error handling: Settings → Error Workflow → Continue On Fail
  • Consider adding a Merge node to collect results before final logging

Form URL Management:

  • Test URL changes on every workflow edit
  • Production URL is stable but tied to workflow ID
  • Deleting and recreating workflow generates new production URL

Authentication Edge Cases:

  • Notion integrations expire if not used for 90 days
  • Slack tokens expire if app is uninstalled from workspace
  • Both require manual token refresh in n8n credentials

Data Validation:

  • n8n Form Trigger validates email format client-side only
  • Add server-side validation using IF node:
{{ $json.Email.includes('@') && $json.Email.includes('.') }}
Enter fullscreen mode Exit fullscreen mode

Cost Optimization

n8n Cloud:

  • Free tier: 5,000 workflow executions/month
  • Each form submission = 1 execution
  • Parallel nodes count as single execution

Notion API:

  • Free for API usage
  • Storage limits based on workspace plan

Slack API:

  • Free for standard messages
  • No per-message costs

Prerequisites

You'll need:

Official documentation:

Get the Complete Workflow Configuration

This tutorial covers the API integration architecture and data flow. For the complete n8n workflow JSON file with all node configurations, and a video walkthrough of the setup process, check out the full implementation guide.

Top comments (0)