What Are Webhooks?
Webhooks are a powerful tool for developers that allow you to send real-time data from one application to another whenever a specific event occurs. In RankPill, you can use a webhook to automatically send all the data for a newly published article to a URL of your choice.
This enables you to create custom integrations with any service that can receive an HTTP POST request, such as:
- A Next.js, Hugo, or Jekyll site
- A custom-built CMS
- A Zapier or Make.com automation workflow
- A serverless function (e.g., AWS Lambda, Vercel Functions)
- A Discord or Slack notification channel
How to Set Up a Webhook
-
Navigate to Webhook Settings: Go to
Settings
>Integrations
in your RankPill dashboard and click on the "Webhooks" integration. -
Enter Your Webhook URL: In the input field, paste the public URL of the endpoint you've created to receive the webhook data. This URL must be able to accept a
POST
request with a JSON payload. -
Connect and Save: Click "Connect". RankPill will securely store your URL and generate a unique Secret Key.
-
Copy Your Secret Key: The secret key is essential for verifying that the incoming requests are genuinely from RankPill. Copy this key and store it securely in your application's environment variables (e.g., as
RANKPILL_WEBHOOK_SECRET
).
Verifying the Signature
To ensure the security of your endpoint, you must verify the signature of every incoming webhook request. We include a signature in the X-RankPill-Signature
header of each request.
The signature is a HMAC SHA-256 hash, created using your Secret Key and the raw JSON payload of the request.
Here's an example of how to verify the signature in a Next.js API route:
// /pages/api/rankpill-webhook.js
import crypto from 'crypto';
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ message: 'Method Not Allowed' });
}
// 1. Get the signature from the headers
const signature = req.headers['x-rankpill-signature'];
if (!signature) {
return res.status(401).json({ message: 'No signature provided.' });
}
// 2. Get the raw request body
// Note: It's crucial to use the raw, unparsed body for the hash calculation.
// The following line is specific to Next.js; your framework may differ.
const rawBody = await getRawBody(req);
// 3. Compute your own signature
const secret = process.env.RANKPILL_WEBHOOK_SECRET;
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
// 4. Compare the signatures
if (signature !== expectedSignature) {
return res.status(401).json({ message: 'Invalid signature.' });
}
// If the signature is valid, process the article data
const article = JSON.parse(rawBody);
console.log('Successfully received article:', article.title);
// TODO: Add your logic here to save the article, create a file, etc.
res.status(200).json({ message: 'Webhook received successfully!' });
}
// Helper to get the raw body in Next.js
function getRawBody(req) {
return new Promise((resolve, reject) => {
const chunks = [];
req.on('data', chunk => chunks.push(chunk));
req.on('end', () => resolve(Buffer.concat(chunks)));
req.on('error', reject);
});
}
Payload Data Structure
The webhook will send a cleaned article object containing only the public content data as a JSON payload. Here is an example of the data you can expect to receive:
{
"title": "How to Build Backlinks for Better SEO",
"content_html": "<h1>How to Build Backlinks for Better SEO</h1><p>Building high-quality backlinks is one of the most important...</p>",
"content_markdown": "# How to Build Backlinks for Better SEO\n\nBuilding high-quality backlinks is one of the most important...",
"slug": "how-to-build-backlinks-for-better-seo",
"meta_description": "Learn proven strategies to build high-quality backlinks that will improve your website's search engine rankings and drive more organic traffic.",
"status": "published",
"featured_image": "https://images.unsplash.com/photo-1516321318423-f06f85e504b3",
"published_url": "https://yourblog.com/blog/how-to-build-backlinks-for-better-seo",
"scheduled_date": null,
"published_at": "2024-03-15T10:30:00Z"
}
By using this data, you can dynamically create pages, update your content, or trigger any other custom workflow you can imagine.