תגיות SEO ב-head

מה בדיוק נכנס ל-head של כל עמוד ב-WizzoCMS ובאיזה סדר, איך SEO::set, seo_center ו-PAGE::add_meta משתלבים, ואיך לשלוט ב-robots, favicon ו-base href.

⏱ 5 דק' קריאה 874 מילים ערוך דף זה ב-GitHub

את ה-<head> של כל עמוד באתר הציבורי בונה PAGE::output, לא ה-theme. הבקר מגדיר ערכים (SEO::set, PAGE::add_meta, PAGE::$robots), והליבה מדפיסה אותם בסדר קבוע. העמוד הזה מראה את הסדר הזה ואת נקודות ההשפעה שלכם; את הפרטים המלאים של מחלקת SEO, של FormInput_SEO ושל חבילת ה-SEO תמצאו ב-SEO למפתחי אתר, ב-SEO (רפרנס) וב-חבילת ה-SEO.

סדר התגיות ב-<head>#

כך נראה ה-<head> של עמוד באתר הציבורי (CONFIG::$system_type == "client"):

#מה נפלטמקור
1<meta http-equiv="Content-Type" ... charset=utf-8>קבוע
2<title>, og:*, twitter:*, <meta name="description">, <meta name="keywords">, twitter:card ותגית האימות של Search ConsoleSEO::tags_summary()
3<base href="<protocol>://<original_site_url>">CONFIG::$protocol, CONFIG::$original_site_url
4תגי CSS של אזור head, ואז תגי JS של אזור headPAGE::IncludeJsCss (ראו צינור הנכסים)
5תגים שנרשמו עם PAGE::add_meta($val) (אזור head, ברירת מחדל)PAGE::print_meta_tags("head")
6<meta name="ROBOTS" content="...">PAGE::$robots, ברירת מחדל "ALL"
7<meta name="copyright" content="2003-2022, Wizzo CMS3.0">נפלט אלא אם CONFIG::$show_wizzo_credits === false
8<link rel="shortcut icon">PAGE::$favicon, ברירת מחדל /favicon.ico
9JSON-LD של WebPageSEO::get_schema("WebPage")
10סקריפטים מהפאנל Scripts עם area = headטבלת scripts

האלמנט <html> נפלט עם lang="he" קבוע ו-dir לפי CONFIG::$platform_data["direction"]. בפאנל הניהול ה-<head> שונה: כותרת <seo_title> | CMS, favicon של הפאנל, וללא JSON-LD וללא סקריפטים של האתר.

הערה
lang="he" קבוע בקוד, גם באתרים רב-לשוניים. אם אתר באנגלית צריך lang="en", hreflang או alternate אחרים, הוסיפו אותם ב-PAGE::add_meta. הליבה לא מדפיסה hreflang ולא rel="canonical" (ראו SEO למפתחי אתר).

מה אתם קובעים#

כותרת, תיאור ו-Open Graph#

class news extends wz_controller
{
    function item()
    {
        $row = DB::query("news", ["id" => (int)$_GET["id"]])->get_row();
        if (!$row) return "ERRORPAGE";

        SEO::set("title", $row["title"]);               // meta_title וגם og_title
        SEO::set("description", $row["summary"]);       // meta_description וגם og_description
        SEO::set("image", (int)$row["image_id"]);       // מספר = STORAGE::get_thumb(id, 1200, 627)
        SEO::set("url", CONFIG::$site_url . "news/" . (int)$row["id"]);
        SEO::set("og_type", "article");                 // מפתח לא מוכר נשמר כמו שהוא

        return $this->view("news/item", ["row" => $row]);
    }
}

SEO::set (כינוי ל-SEO::set_var) מפעיל strip_tags על title, description ו-keywords. שדות שלא הוגדרו מקבלים בסוף ברירת מחדל מהפלטפורמה: seo_title, seo_description ו-seo_keywords מ-CONFIG::$platform_data. כשלא הוגדרה כותרת בכלל, שם האתר לא מתווסף שוב אחרי הכותרת.

דריסה מהפאנל: seo_center#

אחרי שהבקר סיים, tags_summary() בודק אם יש רשומה בטבלת seo_center לעמוד הזה, ואם כן היא דורסת את מה שהבקר קבע, שדה אחר שדה (שדה ריק ברשומה מדולג):

  1. לפי הנתיב הנוכחי: page_key שווה לנתיב (בלי / בתחילה ובסוף, אחרי urldecode) ו-is_by_url = 1.
  2. אם לא נמצאה, לפי SEO::$page_key (מוגדר עם SEO::set_key("news_5")) ו-is_by_url = 0.

כלומר מי שעורך את ה-SEO בפאנל, בדרך כלל דרך FormInput_SEO, תמיד מנצח את ברירות המחדל שבקוד. עמודות מבניות של הטבלה (id, ord, lang, platform_id, is_by_url ועוד) מסוננות ולא הופכות ל-meta.

תגים מותאמים אישית ו-robots#

// תג נוסף ל-head
PAGE::add_meta('<link rel="canonical" href="' . htmlspecialchars(CONFIG::$site_url . "news/5", ENT_QUOTES) . '">');

// תג בסוף ה-body (למשל סקריפט מדידה)
PAGE::add_meta('<script>/* ... */</script>', "body_end");

// עמוד שלא צריך להיכנס לאינדקס
PAGE::$robots = "noindex, follow";

// כיבוי favicon (למשל בדף שמגיש favicon בעצמו)
PAGE::$favicon = false;

add_meta($val, $area = "head") מקבל HTML גולמי ומדפיס אותו כפי שהוא, בלי escaping. אזורים חוקיים: head, body_start, body_end.

שימו לב
PAGE::add_meta לא מסנן כלום. ערך שמגיע מקלט משתמש חייב לעבור htmlspecialchars לפני שהוא נכנס ל-HTML שאתם בונים (ראו XSS).

מלכודות ידועות#

אזהרה

אל תשתמשו ב-SEO::get_schema("Organization") ובמיוחד לא ב-get_schema("NewsArticle"). המימוש מכיל נתוני דוגמה של אתר אחר: לוגו מדומיין חיצוני, מחבר "משה משה" ותאריכים קבועים מ-2021. רק WebPage בטוח, והוא נפלט אוטומטית. בנו JSON-LD אחר בעצמכם ורשמו אותו עם PAGE::add_meta. הדוגמה המלאה ב-SEO למפתחי אתר.

שימו לב
<title> נפלט מהערך כפי שהוא, בלי קידוד HTML (CORE-47): & בכותרת נשאר &. שאר ה-meta עוברים htmlspecialchars. בנוסף, שאילתות seo_center רצות בלי מטמון בכל רינדור של עמוד שלא הוגש מ-מטמון עמודים, והחיפוש לא מסנן לפי פלטפורמה או שפה, כך שאותו נתיב מקבל אותו meta בכל הדומיינים.

שימו לב
PAGE::$robots אינו מאופס ב-PAGE::reset. הוא משפיע על כל מה שנרנדר באותה בקשה. ערך שהוגדר לפני PAGE::load (ב-application/includes/init.php) נשאר.

הערה

עמוד שהוגש מהמטמון המלא כבר כולל את כל ה-<head> שנבנה בזמן השמירה. שינוי ב-seo_center או בקוד לא יופיע עד שהמטמון פג או מנוקה (ניקוי מטמון).

ראו גם#

מצאתם טעות או חוסר? תקנו את הדף או פתחו Issue בריפו. התיעוד נכתב מתוך הקוד של ליבה 5.0.115.