Social & Open Graph Analysis
Issue No: 97
Category: Social & Open Graph
Issue type: Issue
Priority: CRITICAL
Description
Issue 97 is the umbrella bundle for the full Social & Open Graph toggle group. It validates all 13 script-checkable items together (97, 99, 119-129) so OG, article, and Twitter metadata are evaluated as one consolidated social metadata health check.
Missing, empty, or invalid tags reduce preview quality, weaken trust signals, and can lower click-through rate from social surfaces.
How do we capture it
- Request final page HTML after redirects (store final URL and status).
- Parse head metadata from raw response HTML (no JS execution).
- Extract all social metadata tags:
meta[property]where property starts withog:orarticle:meta[name]where name starts withtwitter:
- Normalize keys to lowercase and trim whitespace from content.
- Build property maps:
- first non-empty value per property
- all raw values list per property
- duplicate-property list where count > 1
- Validate issue-specific rules for all 13 Social & Open Graph checklist items:
- 97, 99, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129
- For URL fields (
og:url,og:image) validate absolute scheme and URL syntax. - For datetime fields (
article:published_time,article:modified_time) validate parseable ISO-8601-like format. - For image dimension fields (
og:image:width,og:image:height) validate positive integers. - For article-only fields (
article:*) evaluate only when page is article-like (og:type = articleor URL/content heuristics mark it as article). - Persist normalized values, validation booleans, missing/empty arrays, duplicates, and issue flags.
What to store
| Field | Type | Comment |
|---|---|---|
has_open_graph_tags | BOOLEAN | True when at least one og:* tag exists. |
has_article_open_graph_tags | BOOLEAN | True when at least one article:* property exists. |
og_title | TEXT | Normalized first non-empty og:title value. |
og_description | TEXT | Normalized first non-empty og:description value. |
og_type | TEXT | Normalized first non-empty og:type value. |
og_url | TEXT | Normalized first non-empty og:url value. |
og_image | TEXT | Normalized first non-empty og:image value. |
og_image_width | TEXT | Normalized first non-empty og:image:width value. |
og_image_height | TEXT | Normalized first non-empty og:image:height value. |
og_image_alt | TEXT | Normalized first non-empty og:image:alt value. |
og_site_name | TEXT | Normalized first non-empty og:site_name value. |
og_locale | TEXT | Normalized first non-empty og:locale value. |
article_published_time | TEXT | Raw normalized article:published_time value. |
article_modified_time | TEXT | Raw normalized article:modified_time value. |
article_author | TEXT | Raw normalized article:author value (author attribution). |
article_section | TEXT | Raw normalized article:section value. |
article_tags | TEXT[] | All normalized article:tag values (deduplicated). |
twitter_site | TEXT | Normalized first non-empty twitter:site value. |
twitter_creator | TEXT | Normalized first non-empty twitter:creator value. |
twitter_image_alt | TEXT | Normalized first non-empty twitter:image:alt value. |
has_twitter_card_tags | BOOLEAN | True when at least one twitter:* tag exists. |
og_required_tags_present | BOOLEAN | True when all core OG fields are present and non-empty. |
og_missing_required_tags | TEXT[] | Missing required OG fields list. |
og_empty_required_tags | TEXT[] | Required OG fields that exist but are empty. |
og_url_is_valid | BOOLEAN | True when og:url is an absolute HTTP/HTTPS URL. |
og_image_is_valid | BOOLEAN | True when og:image is an absolute URL. |
og_image_width_is_valid | BOOLEAN | True when og:image:width is a positive integer. |
og_image_height_is_valid | BOOLEAN | True when og:image:height is a positive integer. |
og_locale_is_valid | BOOLEAN | True when locale matches expected pattern like en_US. |
article_published_time_is_valid | BOOLEAN | True when published time is parseable datetime. |
article_modified_time_is_valid | BOOLEAN | True when modified time is parseable datetime. |
article_author_is_present | BOOLEAN | True when article:author exists and is not blank. |
article_section_is_present | BOOLEAN | True when article:section exists and is not blank. |
article_tag_is_present | BOOLEAN | True when at least one non-empty article:tag exists. |
twitter_site_is_present | BOOLEAN | True when twitter:site exists and is not blank. |
twitter_creator_is_present | BOOLEAN | True when twitter:creator exists and is not blank. |
twitter_image_alt_is_present | BOOLEAN | True when twitter:image:alt exists and is not blank. |
is_article_like_page | BOOLEAN | Classifier for applying article-specific rules. |
og_duplicates_json | JSONB | Map of duplicate OG/article properties with all detected values. |
twitter_duplicates_json | JSONB | Map of duplicate twitter properties with all detected values. |
social_meta_snapshot_json | JSONB | Full normalized snapshot of parsed OG/article key-values for diagnostics. |
social_missing_tags_by_issue_json | JSONB | Missing/empty fields grouped by issue ID. |
social_invalid_fields_by_issue_json | JSONB | Invalid fields grouped by issue ID. |
social_og_bundle_issue_detected | BOOLEAN | True when any issue in this bundle is triggered. |
Condition for trigger
Conditions on database fields triggering issues.
-
Trigger Rule 97: Open Graph tags set (bundle baseline)
- Target Field:
has_open_graph_tags - Evaluation Logic:
has_open_graph_tags = FALSE OR og_required_tags_present = FALSE - Severity: IMPORTANT
- Diagnostic Message: "Open Graph baseline tags are missing or incomplete."
- Target Field:
-
Trigger Rule 99: Twitter Card meta tags
- Target Field:
has_twitter_card_tags - Evaluation Logic:
has_twitter_card_tags = FALSE - Severity: STANDARD
- Diagnostic Message: "Twitter Card metadata layer is not implemented."
- Target Field:
-
Trigger Rule 119: og:image:width and og:image:height missing/invalid
- Target Field:
og_image_width,og_image_height - Evaluation Logic:
og_image IS NOT NULL AND (og_image_width IS NULL OR btrim(og_image_width) = '' OR og_image_height IS NULL OR btrim(og_image_height) = '' OR og_image_width_is_valid = FALSE OR og_image_height_is_valid = FALSE) - Severity: IMPORTANT
- Diagnostic Message: "OG image dimensions are missing or invalid."
- Target Field:
-
Trigger Rule 120: og:locale missing/invalid
- Target Field:
og_locale - Evaluation Logic:
og_locale IS NULL OR btrim(og_locale) = '' OR og_locale_is_valid = FALSE - Severity: IMPORTANT
- Diagnostic Message: "OG locale metadata is missing or malformed."
- Target Field:
-
Trigger Rule 121: og:site_name missing
- Target Field:
og_site_name - Evaluation Logic:
og_site_name IS NULL OR btrim(og_site_name) = '' - Severity: IMPORTANT
- Diagnostic Message: "OG site name metadata is missing."
- Target Field:
-
Trigger Rule 122: og:image:alt missing
- Target Field:
og_image_alt - Evaluation Logic:
og_image IS NOT NULL AND (og_image_alt IS NULL OR btrim(og_image_alt) = '') - Severity: IMPORTANT
- Diagnostic Message: "OG image exists without alternative text metadata."
- Target Field:
-
Trigger Rule 123: article:published_time missing/invalid
- Target Field:
article_published_time - Evaluation Logic:
is_article_like_page = TRUE AND (article_published_time IS NULL OR btrim(article_published_time) = '' OR article_published_time_is_valid = FALSE) - Severity: IMPORTANT
- Diagnostic Message: "Article publish timestamp metadata is missing or invalid."
- Target Field:
-
Trigger Rule 124: article:modified_time missing/invalid
- Target Field:
article_modified_time - Evaluation Logic:
is_article_like_page = TRUE AND (article_modified_time IS NULL OR btrim(article_modified_time) = '' OR article_modified_time_is_valid = FALSE) - Severity: IMPORTANT
- Diagnostic Message: "Article modified timestamp metadata is missing or invalid."
- Target Field:
-
Trigger Rule 125: article:author missing/invalid
- Target Field:
article_author - Evaluation Logic:
is_article_like_page = TRUE AND (article_author IS NULL OR btrim(article_author) = '' OR article_author_is_present = FALSE) - Severity: STANDARD
- Diagnostic Message: "Article author attribution metadata is missing."
- Target Field:
-
Trigger Rule 126: article:section and article:tag missing
- Target Field:
article_section,article_tags - Evaluation Logic:
is_article_like_page = TRUE AND ((article_section IS NULL OR btrim(article_section) = '' OR article_section_is_present = FALSE) OR article_tag_is_present = FALSE) - Severity: STANDARD
- Diagnostic Message: "Article category metadata (section/tag) is missing."
- Target Field:
-
Trigger Rule 127: twitter:site missing
- Target Field:
twitter_site - Evaluation Logic:
twitter_site IS NULL OR btrim(twitter_site) = '' OR twitter_site_is_present = FALSE - Severity: STANDARD
- Diagnostic Message: "Twitter site handle metadata is missing."
- Target Field:
-
Trigger Rule 128: twitter:creator missing on article-like pages
- Target Field:
twitter_creator - Evaluation Logic:
is_article_like_page = TRUE AND (twitter_creator IS NULL OR btrim(twitter_creator) = '' OR twitter_creator_is_present = FALSE) - Severity: STANDARD
- Diagnostic Message: "Twitter creator handle metadata is missing for article-like content."
- Target Field:
-
Trigger Rule 129: twitter:image:alt missing
- Target Field:
twitter_image_alt - Evaluation Logic:
og_image IS NOT NULL AND (twitter_image_alt IS NULL OR btrim(twitter_image_alt) = '' OR twitter_image_alt_is_present = FALSE) - Severity: IMPORTANT
- Diagnostic Message: "Twitter image alt metadata is missing."
- Target Field:
-
Trigger Rule OG core consistency: og:type, og:title, og:description, og:url, og:image
- Target Field:
og_type - Evaluation Logic:
og_type IS NULL OR btrim(og_type) = '' OR og_title IS NULL OR btrim(og_title) = '' OR og_description IS NULL OR btrim(og_description) = '' OR og_url IS NULL OR btrim(og_url) = '' OR og_url_is_valid = FALSE OR og_image IS NULL OR btrim(og_image) = '' OR og_image_is_valid = FALSE - Severity: IMPORTANT
- Diagnostic Message: "Core Open Graph metadata is incomplete, empty, or invalid."
- Target Field:
-
Trigger Rule Final: Social & Open Graph issue state
- Target Field:
social_og_bundle_issue_detected - Evaluation Logic:
social_og_bundle_issue_detected = TRUE - Severity: CRITICAL
- Diagnostic Message: "Computed summary flag becomes true when any of the 13 Social & Open Graph checklist items is triggered."
- Target Field:
Sources
- Open Graph protocol (official): https://ogp.me/
- Facebook sharing crawler guidance (Meta): https://developers.facebook.com/docs/sharing/webmasters/
- Facebook Sharing Debugger (Meta): https://developers.facebook.com/tools/debug/
- LinkedIn post inspector: https://www.linkedin.com/post-inspector/
- X (Twitter) cards markup reference: https://developer.x.com/en/docs/x-for-websites/cards/overview/markup
- Google Search Central (metadata + snippets context): https://developers.google.com/search/docs/appearance/snippet
- MDN meta element reference: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meta
Long description
Open Graph is a metadata protocol used by social platforms to understand what title, description, image, URL, and contextual metadata should be shown when a page is shared. This document treats Issue 97 as the master bundle that groups all 13 Social & Open Graph checklist checks together: 97, 99, and 119-129.
When social metadata is implemented correctly, link previews usually show a meaningful title (og:title), a concise summary (og:description), a stable public URL (og:url), a visual preview image (og:image), an expected content type (og:type), image dimensions (og:image:width, og:image:height), locale (og:locale), and attribution metadata for article and Twitter contexts.
This bundle includes these 13 required checks under one issue umbrella:
- 97: Open Graph tags baseline
- 99: Twitter Card tags baseline
- 119:
og:image:width+og:image:height - 120:
og:locale - 121:
og:site_name - 122:
og:image:alt - 123:
article:published_time - 124:
article:modified_time - 125:
article:author - 126:
article:section+article:tag - 127:
twitter:site - 128:
twitter:creator - 129:
twitter:image:alt
Common failure scenarios checked by the crawler:
- No OG tags: Shared link may show random text/image or no image at all.
- No Twitter tags: X/Twitter cards may be incomplete or fallback to unpredictable snippets.
- Image tag exists but no dimensions: Platforms may render inconsistent preview crops.
- Locale/site/alt missing: Card context and accessibility quality are reduced.
- Article page without author metadata: Reduced editorial trust and weaker attribution in social/AI surfaces.
- Duplicate OG keys with conflicting values: Platform may choose unexpected value; preview changes unpredictably.
How to Fix
- Add core OG tags in the server-rendered
<head>for every indexable page template. - Ensure core OG keys are present and non-empty (
og:title,og:description,og:type,og:url,og:image). - Add
og:image:widthandog:image:heightwith valid positive integer values. - Add supporting OG context tags:
og:locale,og:site_name,og:image:alt. - Add Twitter layer tags:
twitter:site,twitter:creator(for article-like pages),twitter:image:alt. - On article-like pages, add article metadata:
article:published_time,article:modified_time,article:author,article:section,article:tag. - Use absolute HTTPS URLs for
og:urlandog:image. - Remove duplicate/conflicting OG/article/twitter keys from head output.
- Re-scrape the page in Meta Sharing Debugger or LinkedIn Post Inspector.
- Re-run XeoPix crawler and confirm issue flags 97, 99, and 119-129 are passing.