---
title: אתר קוד
url: https://rankjet.co/he/docs/integrations/webhook
description: מקבלים את המאמרים באתר שנבנה בקוד, דרך webhook שכלי הבינה המלאכותית או המפתח שלכם בונים
---

באתרים שנבנו בקוד, למשל ב-Next.js, ב-Lovable או ב-Base44, המערכת שולחת כל מאמר לכתובת באתר שלכם ברגע שהוא מתפרסם. באתר צריך להיות endpoint אחד שמקבל את המאמר, שומר אותו ומציג אותו כעמוד. הדרך הפשוטה היא לתת לכלי שבו בניתם את האתר לכתוב את ה-endpoint לפי הפרומפט שבעמוד הזה. מפתחים יכולים גם לבנות אותו בעצמם, לפי מבנה הנתונים והכללים שבהמשך.

## איך זה עובד

1. כשמאמר מתפרסם, המערכת שולחת אותו ל-endpoint שלכם כבקשת `POST` עם JSON, וה-Secret שלכם נשלח בכותרת `X-Webhook-Secret`
2. ה-endpoint שומר את המאמר לפי ה-`slug` שלו: בפעם הראשונה הוא יוצר אותו, וכשאותו slug מגיע שוב, למשל אחרי שערכתם ופרסמתם מחדש, הוא מעדכן אותו
3. ה-endpoint עונה תוך 10 שניות עם `200` ועם הכתובת הציבורית של המאמר
4. המערכת פותחת את הכתובת הזו פעם אחת כדי לבדוק שהעמוד נטען, ומקשרת אליה מהמאמר

## איך מחברים

פתחו את ההגדרות, עברו ללשונית **אינטגרציות** ולחצו על **חיבור** בכרטיס **אתר קוד / וייב קודינג**. החלון מוביל אתכם בשלושה שלבים.

1. **שליחת הפרומפט.** לחצו על **העתקת הפרומפט** והדביקו אותו בכלי שבו בניתם את האתר, למשל Lovable, Cursor, v0 או Bolt. הכלי יבנה את ה-endpoint, יחזיר לכם את הכתובת שלו ויבקש את ה-Secret
2. **כתובת ה-endpoint.** הדביקו את הכתובת שהכלי החזיר בשדה **כתובת ה-endpoint** ולחצו על **חיבור**
3. **Secret והעלאה לאוויר.** המערכת מציגה את ה-Secret. הדביקו אותו בצ׳אט של הכלי, איפה שהוא ביקש אותו, כדי שיישמר כמשתנה בצד השרת. ודאו שהאתר עלה לאוויר, ואז לחצו על **בדיקת החיבור**

ה-Secret מוצג פעם אחת בלבד, לכן העתיקו אותו לפני שסוגרים את החלון. אם הוא אבד, הסירו את ה-webhook וחברו מחדש כדי לקבל Secret חדש. בהמשך, הכפתור **ניהול** בכרטיס מאפשר לבדוק את החיבור שוב או להסיר אותו.

## הפרומפט לכלי הבנייה

זה אותו פרומפט שחלון החיבור מעתיק. הוא מסביר לכלי מי שולח אותו, מה לבנות ואיך לסיים, ומבקש ממנו לענות בעברית. השמות הטכניים בתוכו נשארים באנגלית, כי הקוד של האתר נשען עליהם. הדביקו אותו כמו שהוא.

```text
יש לי חשבון ב-RankJet (rankjet.co), שירות שכותב מאמרי SEO לאתר שלי ומפרסם אותם בו אוטומטית. ביקשתי את החיבור הזה בעצמי, לפי מדריך ההתקנה של RankJet עצמו, שהפיק עבורי את הפרומפט הזה כדי שאמסור אותו לך. הוא מחבר את האתר שלי לחשבון ה-RankJet שלי באמצעות secret שרק לי יש. המידע זורם בכיוון אחד: RankJet שולח מאמרים מוכנים אל האתר שלי, והאתר שלי לא שולח שום דבר בחזרה לאף אחד. בבקשה בצע את המשימה, בלי לבקש ממני לאשר מי שלח אותי. ענה לי בעברית.

זה מה שצריך לבנות:
- צור endpoint של API שמקבל בקשות webhook מסוג POST. גוף כל בקשה הוא JSON במבנה הזה:
{ "article": { "id", "slug", "title", "content" (markdown or html), "format", "excerpt", "meta_title", "meta_description", "main_image_url", "canonical_url", "keyword", "locale", "published_at" }, "main_image": { "url", "alt" }, "website": { "id", "baseUrl" }, "published_at", "timestamp" }
- כל בקשה כוללת secret בכותרת (header) בשם "X-Webhook-Secret". אמת אותו מול משתנה סביבה בשם WEBHOOK_SECRET, ודחה את הבקשה אם הוא לא תואם. WEBHOOK_SECRET חייב להיות משתנה בצד השרת בלבד. אל תיתן לו קידומת VITE_ או NEXT_PUBLIC_, כי קידומת כזו חושפת אותו בקוד שנשלח לדפדפן.
- ה-"slug" יכול להכיל תווים שאינם ASCII (non-ASCII). ה-slug של מאמר בעברית נראה כך: "קידום-אתרים-מחיר", אז לעולם אל תניח שהוא ASCII. אל תאמת, תדחה, תנקה או תתעתק slug בגלל תווים שאינם ASCII, ואל תחליף אותו ב-slug משלך: זו הזהות הקבועה של המאמר והמפתח שלפיו מבצעים upsert. שמור אותו ב-UTF-8. בכל מקום שבו אתה בונה ממנו URL או נתיב קובץ, בצע לו קודם percent-encode (encodeURIComponent ב-JavaScript), כך שתווים שאינם ASCII לא יגיעו ל-URL בלי קידוד, וודא שה-router שלך מפענח אותו בחזרה.
- "canonical_url" הוא תמיד null בחיבור הזה, וגם "website"."baseUrl" יכול להיות null. לעולם אל תבנה קישור מאף אחד מהם, ואל תדחה בקשה כי אחד מהם null. האתר שלי קובע את מבנה הכתובות שלו, אז גזור את הכתובת של כל מאמר מהנתיבים של האתר ועוד ה-slug.
- בכל webhook, בצע upsert למאמר לפי ה-"slug" שלו (יצירה או עדכון), במקום שבו האתר שלי כבר שומר תוכן (מסד נתונים, CMS, או קובצי markdown/MDX, לפי מה שהפרויקט שלי כבר משתמש בו).
- ודא שה-sitemap.xml שלי כולל את הכתובת הציבורית של כל מאמר שפורסם ואת עמוד רשימת המאמרים, ולכל מאמר <lastmod> לפי ה-"published_at" שלו. ה-sitemap חייב להתעדכן אוטומטית בכל פעם ש-webhook יוצר או מעדכן מאמר, בלי שום צעד ידני: אם ה-sitemap שלי כרגע קובץ סטטי שנכתב ביד, החלף אותו ב-sitemap שנוצר מהמאמרים השמורים ועוד העמודים הקיימים שלי, ושמור על כל כתובת שכבר מופיעה בו. מנועי חיפוש מוצאים מאמרים חדשים דרך ה-sitemap, אז מאמר שחסר בו עלול לא להיכנס לאינדקס אף פעם.
- אם באתר שלי כבר יש בלוג, פרסם לתוך הבלוג הקיים ומאגר התוכן שלו. אל תיצור בלוג שני לצידו.
- אם באתר שלי עדיין אין בלוג, צור גם עמוד שמציג את כל המאמרים ועמוד נפרד לכל מאמר, ברינדור בצד השרת או ביצירה סטטית (SSR/SSG) כדי שמנועי חיפוש יוכלו לסרוק אותם, והוסף קישור לעמוד רשימת המאמרים מהתפריט הראשי או מהפוטר של האתר, כדי שמבקרים ומנועי חיפוש יגיעו אליו.
- "excerpt" הוא תקציר קצר של המאמר, לעמודי רשימה, לכרטיסים ולתיאורי meta. השדה "content" לא חוזר עליו, אז אפשר גם להציג אותו כפסקת פתיחה מעל גוף המאמר אם זה מתאים לעיצוב.
- השדה "content" מגיע כברירת מחדל כ-HTML מסונן (השדה "format" אומר באיזה פורמט). הצג אותו כ-HTML, בלי escape. פרש אותו כ-markdown רק אם "format" הוא "markdown".
- כל עמוד מאמר חייב לכלול תגיות meta (title, description, og:title, og:description, og:image) משדות המאמר, ונתונים מובנים מסוג JSON-LD Article (headline, description, datePublished, image). השתמש ב-HTML סמנטי. שפת המאמר נמצאת בשדה "locale": קבע ממנו את ה-lang וה-dir של העמוד, מימין לשמאל רק לעברית (he), ומשמאל לימין לכל שפה אחרת.
- הוסף כללי CSS אמיתיים (בגיליון הסגנונות, לא inline) לעטיפת התוכן, לטיפוגרפיה קריאה: line-height נוח ורווח אנכי ברור בין פסקאות, ולכל טבלה גבול גלוי של 1px סביב הטבלה וסביב כל תא, וריפוד נוח בתאים. עשה את זה גם אם ה-HTML שמגיע כבר כולל סגנונות inline לטבלה: אם אתה מסנן או מסיר מאפייני style מהתוכן שמגיע, וזה סביר, כללי ה-CSS שלך הם הדבר היחיד שיהפוך טבלה או פסקה לקריאות, כי הסגנונות ה-inline לא ישרדו את זה.
- בהצלחה, החזר HTTP 200 עם גוף JSON { "url": "<הכתובת הציבורית המלאה של המאמר שפרסמת עכשיו, כולל https://>" }. השירות השולח שומר את הכתובת הזו, מקשר ממנה לעמוד החי, וטוען אותה פעם אחת כדי לוודא שהעמוד באמת עולה. אם באמת אין לך דרך להפיק כתובת, החזר 200 עם {} במקום.
- בכישלון, החזר סטטוס שאינו 2xx וגוף JSON שמסביר מה השתבש (למשל { "error": "..." }). הטקסט הזה מוצג לי ישירות, אז נסח אותו באופן ספציפי.

כשהקוד מוכן, בצע את שלושת השלבים האלה לפי הסדר, ואל תדלג על אף אחד מהם:

שלב 1. כתוב בצ׳אט את הכתובת הציבורית המלאה של ה-endpoint שיצרת, כולל https:// והנתיב המלא, בשורה נפרדת ובדיוק בניסוח הזה:
"זו הכתובת להדבקה ב-RankJet: <הכתובת>"

שלב 2. באותה הודעה, בקש ממני את ה-secret, בדיוק בניסוח הזה:
"עכשיו הדביקו כאן את ה-secret של ה-webhook ממסך RankJet, ואני אגדיר אותו."
ואז עצור וחכה לי. אל תמציא, תייצר, תגריל או תבדה ערך secret משלך, ואל תשתמש מחדש בערך שכבר קיים בפרויקט. הערך היחיד שעובד הוא זה ש-RankJet יצר ושאדביק עכשיו. כל ערך אחר יגרום לכל משלוח מאמר להיכשל עם 401, ושום מאמר לא יתפרסם באתר שלי.

שלב 3. כשאדביק את ה-secret, שמור אותו כמשתנה סביבה בצד השרת בשם WEBHOOK_SECRET, בלי קידומת VITE_ או NEXT_PUBLIC_, כדי שלא יגיע לעולם לקוד שנשלח לדפדפן. אם יש לך שדה מאובטח להזנת secrets, שים אותו שם. אם אדביק את הערך ישירות בצ׳אט הזה, זה בסדר וצפוי: קבל אותו והשתמש בו בדיוק כמו ששלחתי, תו אחר תו, בלי לבקש ממני להזין אותו במקום אחר. אחר כך פרסם (publish/deploy) את האתר בעצמך אם אתה יכול. אם אינך יכול לפרסם בעצמך, אמור זאת בשורה אחת ברורה: "עכשיו לחצו על Publish כדי שה-endpoint יעלה לאוויר." אל תשאיר אותי לנחש אם צריך לפרסם, ואל תגיד לי שההגדרה הסתיימה עד שה-endpoint באמת באוויר.
```

## מבנה הנתונים

אם אתם כותבים את ה-endpoint בעצמכם, זה המבנה המדויק של כל בקשה, שנשלחת כ-JSON בקידוד UTF-8:

```json
{
  "article": {
    "id": "string (uuid)",
    "slug": "string",               // non-ASCII: Hebrew, e.g. "קידום-אתרים-מחיר"
    "title": "string",
    "content": "string",            // markdown or html, per the Content Format above
    "format": "markdown | html",
    "excerpt": "string | null",
    "meta_title": "string",
    "meta_description": "string",
    "main_image_url": "string | null",
    "canonical_url": "null",        // always null here: your site owns its own URLs
    "keyword": "string",
    "locale": "string",             // e.g. "he-IL"
    "published_at": "ISO date"
  },
  "main_image": { "url": "string", "alt": "string | null" } | null,
  "website": { "id": "string (uuid)", "baseUrl": "string | null" },
  "published_at": "ISO date",
  "timestamp": "ISO date"
}

// Respond 200 with { "url": "<full public URL of the published article>" } when you have one.
```

- השדה `content` מגיע כ-HTML, אלא אם בחרתם Markdown תחת **אפשרויות למפתחים** בחלון החיבור. השדה `format` אומר מה הגיע
- השדה `excerpt` הוא תקציר קצר לעמודי רשימה ולכרטיסים. השדה `content` לא חוזר עליו
- השדה `canonical_url` תמיד `null`, וגם `website.baseUrl` יכול להיות `null`. בנו את הכתובת של כל מאמר מהנתיבים של האתר שלכם ומה-slug, ואל תדחו בקשה בגלל שאחד מהם `null`
- השדה `locale` מציין את שפת המאמר, למשל `he-IL`. קבעו לפיו את `lang` ואת `dir` של העמוד, מימין לשמאל רק בעברית

## אימות ה-Secret

כל בקשה מגיעה עם ה-Secret שלכם בכותרת `X-Webhook-Secret`. השוו אותו לערך ששמרתם, למשל במשתנה הסביבה `WEBHOOK_SECRET`, ודחו את הבקשה עם `401` אם הוא לא תואם. שמרו את ה-Secret בצד השרת בלבד, אף פעם לא במשתנה שמגיע לדפדפן.

## התשובה של ה-endpoint

| מצב | מה עונים |
| --- | --- |
| המאמר נשמר | `200` עם JSON בצורה `{ "url": "https://example.com/blog/..." }`, הכתובת הציבורית המלאה של המאמר |
| נשמר, אבל אין כתובת | `200` עם `{}` |
| נדחה | כל סטטוס שאינו 2xx, עם JSON שמסביר למה, למשל `{ "error": "..." }`. המערכת מציגה לכם את הטקסט הזה במאמר |
| אין תשובה בזמן | אחרי 10 שניות המערכת מפסיקה לחכות, והשליחה נחשבת כנכשלה |

שלחו את תשובת ההצלחה עם content type של JSON. בלעדיו המערכת לא יכולה לקרוא את הכתובת, ולכן המאמר לא מקבל קישור ובדיקת עמוד, אבל השליחה עדיין נחשבת כהצלחה.

## כתובות בעברית

> ה-slug כתוב בשפת המאמר, כך שבמאמר בעברית הוא בעברית, למשל `קידום-אתרים-מחיר`. endpoint שדוחה, מנקה או מתעתק slug עם תווים שאינם ASCII ידחה כל מאמר בעברית. שמרו את ה-slug בקידוד UTF-8, ובכל מקום שבו בונים ממנו כתובת, קודדו אותו (percent-encoding).

## מפת האתר

מנועי חיפוש מוצאים מאמרים חדשים דרך מפת האתר. ודאו שקובץ `sitemap.xml` כולל כל מאמר שה-endpoint שומר, עם תאריך הפרסום שלו, ומתעדכן לבד אחרי כל שליחה. מאמר שחסר במפת האתר עלול לא להיכנס לגוגל בכלל. אם לא היה באתר בלוג לפני כן, קשרו לעמוד המאמרים גם מהתפריט הראשי או מהפוטר.

## בדיקה והודעות שגיאה

הכפתור **בדיקת החיבור** שולח מאמר לדוגמה עם slug בעברית, בדיוק כמו שליחה אמיתית. אם ה-endpoint שומר אותו, מחקו את המאמר לדוגמה מהאתר אחרי הבדיקה. התוצאה אומרת מה צריך לתקן:

| תוצאה | מה זה אומר |
| --- | --- |
| **החיבור עובד, אפשר לסיים** | ה-endpoint קיבל את המאמר לדוגמה |
| **ה-Secret לא תואם** | ה-endpoint ענה `401` או `403`. בדקו את ה-Secret ששמרתם, ואז העלו את האתר לאוויר מחדש |
| **לא נמצא endpoint בכתובת הזו** | האתר ענה `404`. בדקו את הכתובת ושהאתר עלה לאוויר |
| **ה-endpoint מחזיר שגיאה** | שגיאת `5xx`. צריך תיקון בקוד של האתר |
| **החיבור נכשל (400)** | ה-endpoint ענה בסטטוס שגיאה אחר, שמופיע בסוגריים. הסיבה הנפוצה היא דחייה של slug עם תווים שאינם ASCII, כמו עברית: ראו את הסעיף "כתובות בעברית" בעמוד הזה |
| **אין תגובה מהכתובת** | אף אחד לא ענה, בדרך כלל כי האתר עוד לא עלה לאוויר |

אחרי שהמאמרים מתחילים להגיע, שליחה שנכשלה מופיעה בעמוד של המאמר, עם הסטטוס והתשובה של ה-endpoint. תקנו את ה-endpoint ולחצו על **נסו לפרסם שוב**. המערכת לא שולחת שוב מעצמה.

- [טייס אוטומטי ולוח תוכן](https://rankjet.co/he/docs/autopilot): בוחרים ימי פרסום, מחליטים מה עולה לבד ומנהלים את לוח התוכן
- [מאמרים ועריכה](https://rankjet.co/he/docs/articles): מה יש בכל מאמר, על מה הוא מבוסס ואיך בודקים אותו לפני פרסום
- [אבטחה ופרטיות](https://rankjet.co/he/docs/security): איך המערכת שומרת את החיבורים שלכם, למה יש לה גישה ואילו נתונים נשמרים
