How to Connect Outrank.so Webhooks to n8n (Free Template)
Download an n8n workflow to auto-publish Outrank articles to GitHub with auth, versioning, and SEO front matter.
By James Le

What you’ll build
When Outrank publishes content, it sends a POST webhook to n8n. This workflow:
- Verifies the request using a Bearer token (Authorization header).
- Splits the incoming batch of articles into individual items.
- Checks your GitHub repo for an existing file by
slug. - Creates or updates an
.mdxfile with front‑matter and article content.
The incoming event is publish_articles and contains an array of articles in the payload (example included below).
Prerequisites
- n8n (self‑hosted or Cloud) with a public base URL (HTTPS).
- Outrank account with the Webhook integration (you’ll add your n8n URL there). Use coupon code TABTABLABS at checkout.
- GitHub repo where articles should live (e.g., a Next.js/Contentlayer or Astro content folder).
- A GitHub Personal Access Token (classic) with at least
reposcope, saved in n8n as a GitHub API credential.
1) Download the workflow (anonymized)
Use the placeholder download link (replace with your hosted file): Download the template
Click to view the n8n workflow JSON
{
"name": "Outrank → n8n: Webhook (POST)",
"nodes": [
{
"parameters": {
"content": "## Set Up\n- Replace `your-secret-webhook-path` with a unique secret path.\n- Set `YOUR_OUTRANK_WEBHOOK_TOKEN` to the token configured in Outrank.\n- Swap `YOUR_GITHUB_USERNAME_OR_ORG` and the repo URL with your GitHub details.\n- Update `YOUR_AUTHOR_NAME_OR_BOT` to the author you want in front matter.\n\nKeep the Authorization expression on the left side as-is.",
"height": 256,
"width": 464
},
"type": "n8n-nodes-base.stickyNote",
"typeVersion": 1,
"position": [
480,
384
],
"id": "beec96bb-18b1-4a08-8bd5-7c8e233be007",
"name": "Sticky Note"
},
{
"parameters": {
"httpMethod": "POST",
"path": "your-secret-webhook-path",
"options": {}
},
"type": "n8n-nodes-base.webhook",
"typeVersion": 2.1,
"position": [
640,
688
],
"id": "b7c43da8-c968-4ea6-82f3-f825d5de4154",
"name": "Webhook",
"webhookId": "b387ceda-aea3-4599-b9d0-9edba29f6756"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.headers.authorization && $json.headers.authorization.split(' ')[1] }}",
"rightValue": "YOUR_OUTRANK_WEBHOOK_TOKEN",
"operator": {
"type": "string",
"operation": "equals",
"name": "filter.operator.equals"
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
848,
784
],
"id": "c593b905-99aa-496a-be74-002bc56ad851",
"name": "Check Auth"
},
{
"parameters": {
"fieldToSplitOut": "body.data.articles",
"options": {
"includeBinary": false
}
},
"type": "n8n-nodes-base.splitOut",
"typeVersion": 1,
"position": [
1072,
784
],
"id": "15c264ff-3741-43e5-a5b8-9534b39ec04a",
"name": "Split Out"
},
{
"parameters": {
"resource": "file",
"operation": "list",
"owner": {
"__rl": true,
"value": "YOUR_GITHUB_USERNAME_OR_ORG",
"mode": "name"
},
"repository": {
"__rl": true,
"value": "https://github.com/YOUR_GITHUB_USERNAME_OR_ORG/YOUR_REPO",
"mode": "url"
},
"filePath": "=content/outrank/"
},
"type": "n8n-nodes-base.github",
"typeVersion": 1.1,
"position": [
1072,
592
],
"id": "9f1c12cd-0adf-4c73-b101-2c441941e698",
"name": "List files",
"webhookId": "63a6c787-396c-4238-bfdd-961bd0c90381"
},
{
"parameters": {
"mode": "expression",
"numberOutputs": 2,
"output": "={{ $('List files').all().some(f => f.json.name === `${$json.slug}.mdx`) }}",
"looseTypeValidation": true
},
"type": "n8n-nodes-base.switch",
"typeVersion": 3.3,
"position": [
1296,
688
],
"id": "d48aaa9d-7fcc-4d6e-ba2b-79b7aa24b5a0",
"name": "Switch"
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"typeValidation": "strict",
"version": 2
},
"conditions": [
{
"leftValue": "={{ $json.content_markdown !== undefined }}",
"rightValue": "=",
"operator": {
"type": "boolean",
"operation": "true",
"singleValue": true
}
}
],
"combinator": "and"
},
"options": {}
},
"type": "n8n-nodes-base.if",
"typeVersion": 2.2,
"position": [
1520,
592
],
"id": "3e1c517f-de81-485f-bad0-b6136e6c43c2",
"name": "If"
},
{
"parameters": {
"resource": "file",
"owner": {
"__rl": true,
"value": "YOUR_GITHUB_USERNAME_OR_ORG",
"mode": "name"
},
"repository": {
"__rl": true,
"value": "https://github.com/YOUR_GITHUB_USERNAME_OR_ORG/YOUR_REPO",
"mode": "url"
},
"filePath": "=content/outrank/{{ $json.slug }}.mdx",
"fileContent": "=---\ntitle: \"{{ $json.title }}\"\ndescription: \"{{ $json.meta_description }}\"\nauthor: YOUR_AUTHOR_NAME_OR_BOT\ndate: {{ $json.created_at.slice(0, 10) }}\ntags: {{ $json.tags }}\nimage_url: {{ $json.image_url }}\n---\n\n{{ $json.content_markdown }}",
"commitMessage": "=add: {{ $json.id }}"
},
"type": "n8n-nodes-base.github",
"typeVersion": 1.1,
"position": [
1744,
592
],
"id": "e25dc23c-3f21-4c80-95da-fb8691d986df",
"name": "Create a file",
"webhookId": "680c657e-c528-486e-8041-963388b0e879"
},
{
"parameters": {
"resource": "file",
"operation": "edit",
"owner": {
"__rl": true,
"value": "YOUR_GITHUB_USERNAME_OR_ORG",
"mode": "name"
},
"repository": {
"__rl": true,
"value": "https://github.com/YOUR_GITHUB_USERNAME_OR_ORG/YOUR_REPO",
"mode": "url"
},
"filePath": "=content/outrank/{{ $json.slug }}.mdx",
"fileContent": "=---\ntitle: \"{{ $json.title }}\"\ndescription: \"{{ $json.meta_description }}\"\nauthor: YOUR_AUTHOR_NAME_OR_BOT\ndate: {{ $json.created_at.slice(0, 10) }}\ntags: {{ $json.tags }}\nimage_url: {{ $json.image_url }}\n---\n\n{{ $json.content_markdown }}",
"commitMessage": "=update: {{ $json.id }}"
},
"type": "n8n-nodes-base.github",
"typeVersion": 1.1,
"position": [
1520,
784
],
"id": "bbb99226-3c87-4a32-b967-0f02a78781b1",
"name": "Edit a file",
"webhookId": "57fed4d5-9627-47bd-ab08-f06f4c0a5b46"
}
],
"pinData": {},
"connections": {
"Webhook": {
"main": [
[
{
"node": "Check Auth",
"type": "main",
"index": 0
},
{
"node": "List files",
"type": "main",
"index": 0
}
]
]
},
"Check Auth": {
"main": [
[
{
"node": "Split Out",
"type": "main",
"index": 0
}
]
]
},
"Split Out": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"List files": {
"main": [
[
{
"node": "Switch",
"type": "main",
"index": 0
}
]
]
},
"Switch": {
"main": [
[
{
"node": "If",
"type": "main",
"index": 0
}
],
[
{
"node": "Edit a file",
"type": "main",
"index": 0
}
]
]
},
"If": {
"main": [
[
{
"node": "Create a file",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "cefb2e37-65c4-4e2e-8807-76d4e3610188",
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "b61787c246f3413fc34965454400ce636f3bc2bcc8d1d5df9c3bcc72ab255ad7"
},
"id": "lCPwJCAqHWZQGqwG",
"tags": [
{
"updatedAt": "2025-10-25T20:07:37.769Z",
"createdAt": "2025-10-25T20:07:37.769Z",
"id": "3bsYGGQ3rKxGh4qM",
"name": "template"
}
]
}2) Import the workflow into n8n
- In n8n, go to Workflows → Import from File.
- Select the anonymized JSON you downloaded above.
- Open the imported workflow to configure placeholders.
3) Replace placeholders with your values
A) Webhook node
- HTTP Method:
POST - Path:
your-secret-webhook-path→ change to a random secret string (e.g.,outrank-9b1de2f0). - Public URL: After saving or activating, n8n will expose:
https://<your-n8n-domain>/webhook/<your-secret-webhook-path>
B) Check Auth (IF) node
-
This checks the header
Authorization: Bearer <token>from Outrank and compares it with a value you control. -
Replace
YOUR_OUTRANK_WEBHOOK_TOKENwith the token you generate and configure on the Outrank side.- Keep the left expression as‑is:
={{ $json.headers.authorization && $json.headers.authorization.split(' ')[1] }}
- Keep the left expression as‑is:
-
Outcome: only requests with the correct Bearer token proceed.
C) GitHub nodes (List / Create / Edit file)
-
In each GitHub node, set the GitHub API credential you saved in n8n.
-
Replace placeholders:
YOUR_GITHUB_USERNAME_OR_ORGhttps://github.com/YOUR_GITHUB_USERNAME_OR_ORG/YOUR_REPO
-
File paths: The template writes to
content/outrank/. Change this if your CMS expects a different folder (e.g.,src/content/blog/).
D) Front‑matter & file content
- Update
author: YOUR_AUTHOR_NAME_OR_BOTto your preferred author. - The template writes
{{ $json.content_markdown }}to the.mdxbody and maps common fields (title,meta_description,created_at,image_url,tags). - You can add more fields or transform content via additional nodes (e.g.,
Function,Set).
4) Activate & connect Outrank
- Activate your n8n workflow.
- In Outrank → Integrations → Webhooks, add your n8n webhook URL:
https://<your-n8n-domain>/webhook/<your-secret-webhook-path> - Set the Access/Bearer token to the same secret you used in Check Auth.
- Save.
5) Test the end‑to‑end flow
Go to https://outrank.so/dashboard/integrations and click the "Play" button to send a test webhook. If you’re new to Outrank, sign up via https://outrank.so/?via=tabtablabs and use coupon code TABTABLABS.

After the request, check your GitHub repo for /content/outrank/sample-article-title-for-testing.mdx.
If the file already existed, the workflow edits it; otherwise it creates it.
6) Troubleshooting
-
401 / Not Authorized in n8n Ensure the Authorization header is present and the Bearer token matches the value you configured in Check Auth.
-
GitHub node errors (403/404/permission)
- Verify the GitHub credential in n8n (token scopes & repo access).
- Ensure
owner,repositoryURL, andfilePathare correct.
-
No file created
- Confirm that
content_markdownexists in the payload (the template has anIfcheck to guard against missing content). - Inspect the Execution log in n8n for node‑by‑node data.
- Confirm that
-
Folder structure differences Adjust
filePathand front‑matter to match your CMS (e.g., adddraft,category, orcanonical_url).
7) Security best practices (quick hits)
- Use a long, random webhook path (e.g.,
outrank-<uuid>). - Validate the Authorization header (already included).
- Optionally restrict by IP allowlist or add a secondary secret inside the body.
- Keep your GitHub PAT scoped as narrowly as possible; rotate regularly.
8) Extending the template (ideas)
- CMS adapters: Instead of GitHub, write to Notion, Sanity, Supabase, or a headless CMS API.
- Image handling: Download images, optimize, and persist to your storage/CDN.
- Link hygiene: Preflight URLs, fix relative links, add UTM params.
- SEO: Auto‑generate
slugwhen missing; enrich front‑matter withreadingTime,og:image, etc. - Notifications: Post to Slack/Discord when a file is created or updated.
Appendix — Where to put your own info (quick checklist)
-
Webhook
- Path:
your-secret-webhook-path→ change to your own secret.
- Path:
-
Check Auth
- Replace
YOUR_OUTRANK_WEBHOOK_TOKENwith the token you configure in Outrank.
- Replace
-
GitHub nodes
- Set GitHub API credential in n8n.
- Replace
YOUR_GITHUB_USERNAME_OR_ORGand repo URL. - Tweak
filePathfolder (content/outrank/) to match your project. - Update
authorin the front‑matter.