Created comprehensive setup guide for syncing Skool community members to email lists via n8n. Includes browser token extraction guide, n8n workflow template, and configuration examples for multiple email platforms (ConvertKit, Mailchimp, ActiveCampaign, SendGrid). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
365 lines
10 KiB
Markdown
365 lines
10 KiB
Markdown
# Skool + n8n Integration - Detailed Step-by-Step Setup
|
||
|
||
**VPS**: ai-termimal
|
||
**Created**: 2025-11-29
|
||
|
||
## Part 1: Extract Authentication Tokens from Skool
|
||
|
||
### Step 1: Open Skool and Browser DevTools
|
||
|
||
1. Log into your Skool community admin panel
|
||
2. Navigate to the Members section
|
||
3. **Right-click** anywhere on the page
|
||
4. Click **"Inspect"** (or press F12)
|
||
5. Click on the **"Network"** tab in DevTools
|
||
6. Make sure it's recording (red circle should be active)
|
||
|
||
### Step 2: Trigger the Export Action
|
||
|
||
1. In the Network tab, click on **"All"** filter
|
||
2. **Do NOT click Export button yet**
|
||
3. With Network tab open and recording, click the **"Export"** button in Skool
|
||
4. You'll see many network requests appear
|
||
5. Look for a request called **"request-bulk-action"** (usually has a yellow icon)
|
||
|
||
### Step 3: Extract Required Headers
|
||
|
||
Click on the **"request-bulk-action"** request:
|
||
|
||
#### A. Get the Request URL
|
||
1. Click on **"Headers"** tab
|
||
2. Find **"Request URL"** at the top
|
||
3. Copy everything up to (and including) `/request-bulk-action`
|
||
4. Example: `https://api.school.com/api/request-bulk-action`
|
||
|
||
#### B. Get the Cookie
|
||
1. Scroll down to **"Request Headers"** section
|
||
2. Find the **"cookie:"** header
|
||
3. Copy the ENTIRE cookie value (will be very long)
|
||
4. Save this in a secure note - you'll need it multiple times
|
||
|
||
#### C. Get the User-Agent
|
||
1. In the same Request Headers section
|
||
2. Find **"user-agent:"**
|
||
3. Copy the value
|
||
4. Example: `Mozilla/5.0 (X11; Linux x86_64)...`
|
||
|
||
#### D. Get the X-AWS-WAF-Token
|
||
1. In the same Request Headers section
|
||
2. Find **"x-aws-waf-token:"**
|
||
3. Copy the entire token value
|
||
4. This is usually a long alphanumeric string
|
||
|
||
#### E. Get the Request Payload
|
||
1. Click on the **"Payload"** tab
|
||
2. You'll see JSON data - copy it exactly
|
||
3. Should look like:
|
||
```json
|
||
{
|
||
"action": "bulk-export",
|
||
"filters": {...}
|
||
}
|
||
```
|
||
|
||
### Step 4: Extract Download URL Parameters
|
||
|
||
After clicking Export, Skool downloads a CSV file:
|
||
|
||
1. In the Network tab, click on **"Doc"** filter (or "Document")
|
||
2. Find a request that shows the downloaded file
|
||
3. Click on it and go to **"Headers"**
|
||
4. In the Request URL, you'll see query parameters:
|
||
- `Expires=...`
|
||
- `Signature=...`
|
||
- `Key-Pair-Id=...`
|
||
5. Copy each of these values
|
||
|
||
**Note**: These values change with each export, but you need them for the n8n workflow structure
|
||
|
||
---
|
||
|
||
## Part 2: Create n8n Workflow
|
||
|
||
### Node 1: Schedule Trigger
|
||
|
||
1. In n8n, add a **"Schedule Trigger"** node
|
||
2. Configure:
|
||
- **Trigger Interval**: Hours
|
||
- **Hours Between Triggers**: 2
|
||
|
||
**Explanation**: Runs every 2 hours to check for new members
|
||
|
||
### Node 2: HTTP Request - Export Members
|
||
|
||
1. Add an **"HTTP Request"** node
|
||
2. Connect it to the Schedule Trigger
|
||
3. Configure:
|
||
|
||
**Authentication**: None
|
||
|
||
**Method**: POST
|
||
|
||
**URL**:
|
||
```
|
||
https://api.school.com/api/request-bulk-action
|
||
```
|
||
|
||
**Send Query Parameters**: ON
|
||
- Name: `type` | Value: `bulk-export-csv`
|
||
- Name: `all-members-selected` | Value: `true`
|
||
- Name: `members-status` | Value: `active`
|
||
|
||
**Send Headers**: ON
|
||
- Name: `accept` | Value: `*/*`
|
||
- Name: `accept-encoding` | Value: `gzip, deflate, br`
|
||
- Name: `accept-language` | Value: `en-US,en;q=0.9`
|
||
- Name: `cache-control` | Value: `no-cache`
|
||
- Name: `content-type` | Value: `application/json`
|
||
- Name: `Cookie` | Value: `[PASTE YOUR COOKIE HERE]`
|
||
- Name: `origin` | Value: `https://www.school.com`
|
||
- Name: `referer` | Value: `https://www.school.com`
|
||
- Name: `user-agent` | Value: `[PASTE YOUR USER-AGENT HERE]`
|
||
- Name: `x-aws-waf-token` | Value: `[PASTE YOUR TOKEN HERE]`
|
||
- Name: `cookie` | Value: `[PASTE YOUR COOKIE HERE]` (lowercase, same value)
|
||
|
||
**Send Body**: ON
|
||
- Body Content Type: JSON
|
||
- Paste the payload JSON you copied earlier
|
||
|
||
**Expected Output**: A JSON response with a `fileId`
|
||
|
||
### Node 3: HTTP Request - Get Download URL
|
||
|
||
1. Add another **"HTTP Request"** node
|
||
2. Connect it to Node 2
|
||
3. Configure:
|
||
|
||
**Method**: GET
|
||
|
||
**URL**:
|
||
```
|
||
https://api.school.com/api/files/{{ $json.fileId }}/download-url
|
||
```
|
||
(Use expression editor to insert `{{ $json.fileId }}` from previous node)
|
||
|
||
**Send Headers**: ON
|
||
- Use the **exact same headers** as Node 2
|
||
|
||
**Send Body**: OFF
|
||
|
||
**Expected Output**: A JSON response with a `data` field containing download URL
|
||
|
||
### Node 4: HTTP Request - Download CSV File
|
||
|
||
1. Add another **"HTTP Request"** node
|
||
2. Connect it to Node 3
|
||
3. Configure:
|
||
|
||
**Method**: GET
|
||
|
||
**URL**:
|
||
```
|
||
{{ $json.data }}
|
||
```
|
||
(Use expression editor to insert the data field from previous node)
|
||
|
||
**Send Query Parameters**: ON
|
||
- Name: `Expires` | Value: `[YOUR EXPIRES VALUE]`
|
||
- Name: `Signature` | Value: `[YOUR SIGNATURE VALUE]`
|
||
- Name: `Key-Pair-Id` | Value: `[YOUR KEY-PAIR-ID VALUE]`
|
||
|
||
**Note**: These values need to be extracted each time OR you can try to parse them from the download URL dynamically
|
||
|
||
**Send Headers**: ON
|
||
- Use the same headers as before
|
||
|
||
**Expected Output**: Binary data (the CSV file) named something like `community-members.csv`
|
||
|
||
### Node 5: Extract from File (CSV)
|
||
|
||
1. Add an **"Extract from File"** node
|
||
2. Connect it to Node 4
|
||
3. Configure:
|
||
|
||
**Operation**: Extract from Binary Data
|
||
**Binary Property**: `data`
|
||
**File Format**: CSV
|
||
**Input Binary Field Name**: `community-members.csv`
|
||
|
||
**Expected Output**: Array of objects with member data (email, name, joined date, etc.)
|
||
|
||
### Node 6: Limit
|
||
|
||
1. Add a **"Limit"** node
|
||
2. Connect it to Node 5
|
||
3. Configure:
|
||
|
||
**Max Items**: `15` (adjust based on expected new members per time interval)
|
||
**Keep**: First items
|
||
|
||
**Explanation**: Since members are sorted by join date (newest first), this grabs only the most recent 15 members. Adjust based on your community growth rate.
|
||
|
||
### Node 7: Loop Over Items
|
||
|
||
1. Add a **"Loop Over Items"** node
|
||
2. Connect it to Node 6
|
||
|
||
**Explanation**: This will process each of the 15 members one at a time
|
||
|
||
### Node 8: Email Platform Integration (Example with ConvertKit)
|
||
|
||
**This part varies based on your email platform. Below is the general logic:**
|
||
|
||
#### Option A: Using Native Integration (if available)
|
||
|
||
1. Add your email platform node (e.g., "ConvertKit", "Mailchimp", "ActiveCampaign")
|
||
2. Configure:
|
||
- **Operation**: Search Subscriber (or similar)
|
||
- **Email**: `{{ $json.email }}` from the loop
|
||
|
||
#### Option B: Using HTTP Request
|
||
|
||
If your platform doesn't have native n8n integration:
|
||
|
||
1. Add **"HTTP Request"** node
|
||
2. Configure based on your email platform's API documentation
|
||
3. Typically: GET request to search for subscriber by email
|
||
|
||
### Node 9: IF Condition
|
||
|
||
1. Add an **"IF"** node
|
||
2. Connect it to Node 8
|
||
3. Configure:
|
||
|
||
**Condition**: Check if subscriber exists
|
||
- **Value 1**: `{{ $json.subscribers }}` or similar (field from email platform)
|
||
- **Operation**: Is Empty (or Length = 0)
|
||
- **Logic**: If TRUE (subscriber doesn't exist), proceed to add them
|
||
|
||
### Node 10: Add Subscriber (True Branch)
|
||
|
||
1. Add your email platform node on the **TRUE** branch
|
||
2. Configure:
|
||
- **Operation**: Create Subscriber
|
||
- **Email**: `{{ $json.email }}`
|
||
- **First Name**: `{{ $json.first_name }}` (adjust field names)
|
||
- **Tags**: Add appropriate tag (e.g., "Skool Member", "New Member")
|
||
|
||
### Node 11: Return to Loop (False Branch)
|
||
|
||
1. Connect the **FALSE** branch back to the Loop Over Items node
|
||
2. This skips existing members
|
||
|
||
---
|
||
|
||
## Part 3: Testing & Deployment
|
||
|
||
### Test the Workflow
|
||
|
||
1. **Manually trigger** the workflow (don't wait for schedule)
|
||
2. Check each node's output:
|
||
- Node 2 should return a `fileId`
|
||
- Node 3 should return a download URL
|
||
- Node 4 should show binary CSV data
|
||
- Node 5 should show parsed member data
|
||
- Node 6 should show limited results
|
||
|
||
3. **Verify email platform**:
|
||
- Check if test members were added
|
||
- Verify tags are applied correctly
|
||
- Test email sequences trigger properly
|
||
|
||
### Activate the Workflow
|
||
|
||
1. Click **"Active"** toggle in n8n
|
||
2. The workflow will now run on schedule
|
||
3. Monitor the executions tab for errors
|
||
|
||
### Monitoring
|
||
|
||
Set up monitoring for:
|
||
- **Failed executions**: Likely due to expired tokens
|
||
- **No new members**: Expected behavior if no one joined
|
||
- **Duplicate additions**: Check your IF logic
|
||
|
||
---
|
||
|
||
## Part 4: Maintenance
|
||
|
||
### Token Refresh
|
||
|
||
When the workflow fails with authentication errors:
|
||
|
||
1. Repeat Part 1 to extract new tokens
|
||
2. Update Node 2, 3, and 4 headers
|
||
3. Re-test the workflow
|
||
|
||
**Recommendation**: Document the refresh process and set a reminder to check weekly
|
||
|
||
### Adjusting the Limit
|
||
|
||
Monitor your community growth:
|
||
- If you're missing new members: Increase the limit
|
||
- If you're wasting operations: Decrease the limit
|
||
- Formula: `Limit = (Expected joins per hour × Hours between triggers) × 1.5`
|
||
|
||
### Scaling Considerations
|
||
|
||
As your community grows:
|
||
- Consider increasing schedule frequency (e.g., every 1 hour)
|
||
- Adjust limit accordingly
|
||
- Monitor n8n execution costs (if using cloud)
|
||
|
||
---
|
||
|
||
## Troubleshooting
|
||
|
||
### Issue: "Authentication Failed"
|
||
**Solution**: Re-extract cookies and tokens from browser
|
||
|
||
### Issue: "No fileId returned"
|
||
**Solution**: Check the request payload matches Skool's current format
|
||
|
||
### Issue: "CSV file empty"
|
||
**Solution**: Verify query parameters and download URL format
|
||
|
||
### Issue: "Subscribers added multiple times"
|
||
**Solution**: Check IF node logic - should skip if subscriber exists
|
||
|
||
### Issue: "Missing recent members"
|
||
**Solution**: Increase the Limit node value
|
||
|
||
---
|
||
|
||
## Security Considerations
|
||
|
||
1. **Never share your cookies or tokens** - they provide full access to your Skool account
|
||
2. Store tokens securely in n8n credentials (not in node configuration)
|
||
3. Use environment variables for sensitive data
|
||
4. Regularly rotate tokens by re-extracting from browser
|
||
5. Monitor for unauthorized access to your email platform
|
||
|
||
---
|
||
|
||
## Next Steps
|
||
|
||
- Customize email welcome sequence in your email platform
|
||
- Set up tags for segmentation (e.g., "Skool Members", "Welcome Sequence Completed")
|
||
- Create broadcast campaigns targeting specific tags
|
||
- Consider adding additional automations (e.g., member activity tracking)
|
||
|
||
---
|
||
|
||
## Resources
|
||
|
||
- n8n Documentation: https://docs.n8n.io
|
||
- Skool Community: https://www.skool.com
|
||
- Original Tutorial: https://www.youtube.com/watch?v=vZaYYzb4y5Y
|
||
|
||
## Support
|
||
|
||
If you need help setting this up, you can:
|
||
- Hire the original tutorial creator (link in video description)
|
||
- Post in n8n community forums
|
||
- Consult with an n8n automation specialist
|