التوثيق
Webhooks الصادرة: البيانات المرسلة والتوقيع
استقبل تنبيهات AutoPSEO وتقاريره بصيغة JSON موقّعة على أي نقطة نهاية HTTPS: ترويسات الطلب وحقول المحتوى وأنواع الأحداث وطريقة التحقق من التوقيع.
يرسل الـ webhook الصادر تنبيهات AutoPSEO وتقاريره المجدولة ورسائله التجريبية وملخصات التقارير إلى نقطة نهاية تديرها أنت، على هيئة طلب POST واحد بصيغة JSON لكل رسالة، موقّع بخوارزمية HMAC-SHA256. استخدمه لتغذية Zapier أو Make أو n8n أو أداة إدارة الحوادث أو شيفرتك الخاصة، دون الحاجة إلى حساب على Slack أو Teams. هل تبحث عن الـ webhook الذي يسلّم المقالات إلى موقعك؟ هذا تابع لمحرك المحتوى: راجع تسليم المحتوى.
إضافة webhook
- في قسم Webhooks الصادرة، انقر على webhook جديد.
- أدخل اسمًا له والصق عنوان URL الخاص بنقطة النهاية. يجب أن يكون HTTPS عامًّا: يُرفض
httpالعادي وlocalhostوالأسماء المنتهية بـ.localأو.internalوالمضيفون الذين لا يحتوي اسمهم على نقطة وعناوين IP الخاصة أو المحلية على مستوى الرابط. - انسخ سر التوقيع الذي يظهر بعد الحفظ. يُعرض مرة واحدة فقط.
- انقر على إرسال اختبار لإرسال حدث
test، ثم اربط التقارير المجدولة أو التنبيهات بالـ webhook.
شكل طلب الـ webhook
كل رسالة هي طلب POST يحمل الترويسات التالية:
| الترويسة | القيمة |
|---|---|
Content-Type | application/json |
User-Agent | AutoPSEO-Webhook/1.0 |
X-AutoPSEO-Event | نوع الحدث، مثل traffic_drop |
X-AutoPSEO-Signature | sha256= متبوعة بـ 64 حرفًا سداسيًّا عشريًّا بأحرف صغيرة |
فيما يلي تنبيه انخفاض الزيارات لموقع من نوع نطاق (domain property) من تشغيل الساعة 06:00 بالتوقيت العالمي المنسّق بتاريخ 12 أكتوبر 2026، منسّقًا للقراءة (أما عند الإرسال الفعلي فهو JSON مضغوط، وقيمتا id وsite_id مختلقتان):
{
"id": "9b2e61f04c3a4d7e8f15a0b6c2d39e47",
"event_type": "traffic_drop",
"severity": "high",
"site_id": "4f0c1e9a2b7d4c58",
"site_url": "sc-domain:example.com",
"occurred_at": "2026-10-12T06:00:04.183Z",
"title": "Traffic drop: example.com",
"text": "Clicks 1,500 vs 2,000 in the previous window (-25.0%).",
"url": "https://app.autopseo.com/property/sc-domain%3Aexample.com",
"payload": {
"fields": [
{ "label": "Metric", "value": "clicks" },
{ "label": "Current", "value": "1,500" },
{ "label": "Baseline", "value": "2,000" },
{ "label": "Window", "value": "7 days (2026-10-05 → 2026-10-11 vs 2026-09-28 → 2026-10-04)" },
{ "label": "Change", "value": "-25.0%" }
],
"table": null,
"detector": "traffic_drop",
"window": 7,
"range": { "start": "2026-10-05", "end": "2026-10-11", "compStart": "2026-09-28", "compEnd": "2026-10-04" },
"result": {
"fired": true,
"metric": "clicks",
"value": 1500,
"baseline": 2000,
"change": -0.25,
"severity": "high",
"summary": "Clicks 1,500 vs 2,000 in the previous window (-25.0%)."
}
},
"source": "autopseo"
}
الحقول العليا متطابقة في جميع الأحداث:
| الحقل | ما يحتويه |
|---|---|
id | سلسلة سداسية عشرية عشوائية من 32 حرفًا، تتغير مع كل طلب |
event_type | ما الذي حدث (انظر القسم التالي) |
severity | critical أو high أو medium أو low للتنبيهات؛ وinfo للتقارير والملخصات والاختبارات |
site_id | معرّف AutoPSEO للموقع، أو null في الاختبارات والموقع التجريبي |
site_url | موقع Search Console، مثل sc-domain:example.com أو https://www.example.com/، أو null في الاختبارات |
occurred_at | وقت إنشاء الرسالة بصيغة ISO 8601 بالتوقيت العالمي المنسّق |
title, text | العنوان والجملة الملخِّصة اللذان يعرضهما Slack وTeams |
url | التقرير داخل AutoPSEO، أو null في الاختبارات |
payload.fields | القيم ذات التسميات التي يعرضها Slack على شكل حقول ويعرضها Teams على شكل facts |
payload.table | columns وrows للتقارير والملخصات، وإلا null |
source | دائمًا autopseo |
النسب تُرسل ككسور عشرية: القيمة -0.25 في change تعني انخفاضًا بنسبة 25%، والقيمة 0.034 في ctr تعني 3.4%.
أنواع الأحداث
event_type | وقت الإرسال | مفاتيح إضافية في payload |
|---|---|---|
traffic_drop, traffic_spike, position_drop, ctr_drop, new_lost_rankings, anomaly, index_flip, rank_drop, audit_regression | عند تفعيل قاعدة تنبيه، سواء حسب الجدول أو عبر اختبار القاعدة | detector وwindow وrange (التواريخ، أو null في index_flip وrank_drop وaudit_regression) وresult |
scheduled_report | عند إرسال تقرير مجدول، سواء حسب الجدول أو عبر إرسال الآن | reportType (summary أو queries أو pages أو rankings) وrange (التواريخ مع label) وtotals وprevious |
report_summary | عندما يستخدم أحدهم إرسال إلى Slack في صفحة تقرير | لا شيء: الأرقام موجودة في fields وtable |
test | عندما ينقر أحدهم على إرسال اختبار في الـ webhook | sample، وقيمته دائمًا true |
يكرر result ما قاسه الكاشف: fired وmetric وvalue وbaseline وchange (تكون null عندما لا توجد قيمة للمقارنة) وseverity وsummary، إضافةً إلى z، وهو الدرجة المعيارية المعدّلة، في حدث anomaly. أما totals وprevious فيحتويان على clicks وimpressions وctr وposition لفترتَي التقرير. تجد وصف ما يقيسه كل كاشف في التنبيهات.
كيفية التحقق من التوقيع
التوقيع هو HMAC-SHA256 للبايتات التي أرسلها AutoPSEO بالضبط، مفتاحه سر التوقيع الخاص بالـ webhook، ويُكتب على هيئة sha256= متبوعة بالقيمة السداسية العشرية بأحرف صغيرة. وللتحقق منه:
- اقرأ جسم الطلب الخام قبل أي تحليل لـ JSON، فالتحليل ثم إعادة التسلسل قد يغيّران البايتات.
- احسب HMAC-SHA256 على تلك البايتات مستخدمًا السر كنص: أي السلسلة المكوّنة من 64 حرفًا كما تظهر تمامًا، دون فك ترميزها من الصيغة السداسية العشرية.
- أضف البادئة
sha256=وقارن الناتج بترويسةX-AutoPSEO-Signatureبمقارنة زمنها ثابت. - ارفض الطلب إذا اختلفا. وإلا فأجب فورًا برمز حالة 2xx ونفّذ الأعمال البطيئة بعد ذلك.
مستقبِل لـ Node.js بلا أي اعتماديات:
import { createServer } from 'node:http';
import { createHmac, timingSafeEqual } from 'node:crypto';
const secret = process.env.AUTOPSEO_WEBHOOK_SECRET;
createServer((req, res) => {
const chunks = [];
req.on('data', (chunk) => chunks.push(chunk));
req.on('end', () => {
const raw = Buffer.concat(chunks);
const expected = Buffer.from('sha256=' + createHmac('sha256', secret).update(raw).digest('hex'));
const received = Buffer.from(String(req.headers['x-autopseo-signature'] || ''));
if (received.length !== expected.length || !timingSafeEqual(received, expected)) {
res.writeHead(401).end();
return;
}
res.writeHead(204).end();
const event = JSON.parse(raw.toString('utf8'));
console.log(event.event_type, event.severity, event.site_url);
});
}).listen(8080);
يأتي فحص الطول أولًا لأن الدالة timingSafeEqual في Node تُطلق خطأً عندما يختلف طولا المخزنين المؤقتين.
قواعد التسليم
- تحصل كل رسالة على محاولة واحدة بمهلة 10 ثوانٍ. أي استجابة غير 2xx تُعدّ فشلًا، وتُحفظ في سجل التسليم مع رمز الحالة وبداية نص استجابتك.
- لا تُتبع عمليات إعادة التوجيه. تفشل الاستجابة 3xx مع ملاحظة تطلب استخدام الرابط النهائي.
- لا تُعاد المحاولة تلقائيًّا بعد مدة. التنبيه الفاشل لا يُعلَّم بأنه أُرسل، لذا يعيد الفحص التالي تقييمه وينشره إن كان لا يزال مفعّلًا: في صباح اليوم التالي لمعظم الكواشف، وفي الساعة التالية لتحولات الفهرسة (index flips). أما التقرير المجدول الفاشل فلا يُعاد إرساله ضمن الفترة نفسها، فاستخدم إرسال الآن بعد إصلاح نقطة النهاية.
- يُنشأ
idلكل طلب، فهو يعرّف عملية تسليم لا حدثًا. ولإزالة التكرار في التنبيهات، اجمعevent_typeوsite_urlوتاريخoccurred_at: فالقاعدة تنشر مرة واحدة على الأكثر لكل موقع في كل يوم بالتوقيت العالمي المنسّق، ما لم يشغّل أحدهم اختبار القاعدة.
سر التوقيع
يعرض AutoPSEO سر التوقيع مرة واحدة عند حفظ الـ webhook، ولا تعرضه القائمة بعد ذلك. احفظه فورًا مع إعدادات المستقبِل لديك، إلى جانب نقطة النهاية التي يحميها.
يُخزَّن عنوان URL نفسه مشفّرًا، ولا تعرض القائمة سوى المضيف وآخر أحرف منه. وحذف الـ webhook يحذف أيضًا كل القواعد التي تنشر إليه. وإذا أردت بطاقة مقروءة في قناة Teams بدلًا من JSON، فاستخدم Microsoft Teams.