Skip to content

The current Open Graph (og:) and Twitter metadata generated by UNA often has formatting issues in the description field #5200

@BrownEbee

Description

@BrownEbee

Purpose of Update

The current Open Graph (og:) and Twitter metadata generated by UNA often has formatting issues in the description field:

  • Missing spaces between sentences when line breaks separate them.
  • Run-on words when lowercase letters are followed by uppercase letters without spacing.
  • Descriptions cut off abruptly without clear indication.

This update introduces cleaning and normalization logic for titles and descriptions before they are injected into meta tags.


Key Improvements

  1. Whitespace normalization

    • Collapses multiple spaces and line breaks into single spaces.
    • Ensures consistent spacing after punctuation (.?!:).
  2. Run-on word correction

    • Adds missing spaces between lowercase+uppercase transitions (e.g., wellBeingwell Being).
  3. Sentence / bullet separation

    • If multiple sentences or items follow without punctuation, they are separated with a middle dot () for clarity.
  4. Ellipsis handling

    • If the description is truncated or does not end with punctuation, "..." is appended.
    • If description length exceeds 200 characters (safe for Facebook/WhatsApp preview), it is cut cleanly and suffixed with "...".
  5. Title cleaning

    • Strips tags and normalizes whitespace.
    • Ensures Open Graph and Twitter titles are consistent.
  6. Generic and neutral fallback

    • If description is truly missing, no hardcoded fallback text is injected.
    • This avoids project-specific branding (so UNA instances remain clean and customizable).

Benefits

  • Improved sharing previews on Facebook, Twitter (X), WhatsApp, Telegram, and other platforms.
  • Consistent formatting across all UNA apps (Spaces, Events, Groups, Photos, etc.).
  • SEO friendliness by ensuring titles and descriptions remain readable and properly spaced.
  • Future-proof: Adds safeguards without locking UNA into project-specific slogans.

👉 Recommendation: Replace the existing Facebook / Twitter Open Graph Metadata block in BxDolTemplate.php with the provided drop-in replacement to standardize metadata across UNA installs.

`// ==========================================
// Facebook / Twitter Open Graph Metadata
// ==========================================

// Image
$bPageImage = !empty($this->aPage['image']);
$sRet .= '';
if ($bPageImage) {
$sRet .= '';
}

// ==========================================
// Title with improved whitespace
// ==========================================
$sHeader = '';
if (isset($this->aPage['header'])) {
$sRawTitle = strip_tags($this->aPage['header']);
$sRawTitle = preg_replace('/\s+/', ' ', $sRawTitle); // collapse spaces/newlines
$sRawTitle = preg_replace('/([a-z0-9])([A-Z])/', '$1 $2', $sRawTitle); // fix run-on words
$sHeader = trim($sRawTitle);
}
$sRet .= '';
$sRet .= '';

// ==========================================
// Description with punctuation/spacing fixes
// ==========================================
$sCleanDesc = '';
if ($bDescription) {
$sRawDesc = strip_tags($sDescription);

// Normalize whitespace
$sRawDesc = preg_replace('/\s+/', ' ', $sRawDesc);

// Fix missing space after punctuation (.?!:)
$sRawDesc = preg_replace('/([.?!:])(\S)/u', '$1 $2', $sRawDesc);

// Fix run-on lowercase+uppercase
$sRawDesc = preg_replace('/([a-z0-9])([A-Z])/', '$1 $2', $sRawDesc);

// Replace multiple sentences without punctuation → bullet separators
$sRawDesc = preg_replace('/\s+(?=[A-Z])/', ' • ', $sRawDesc);

$sCleanDesc = trim($sRawDesc);

}

// If still empty, do not inject fallback text
if ($sCleanDesc !== '') {
// Limit length (safe for FB/WA, prevents cut-off mid-word)
$maxLen = 200;
if (mb_strlen($sCleanDesc) > $maxLen) {
$sCleanDesc = mb_substr($sCleanDesc, 0, $maxLen - 3) . '...';
} else {
// If description does not end with proper punctuation, add "..."
if (!preg_match('/[.!?]$/u', $sCleanDesc)) {
$sCleanDesc .= '...';
}
}

$sRet .= '<meta property="og:description" content="' . bx_html_attribute($sCleanDesc) . '" />';
$sRet .= '<meta name="twitter:description" content="' . bx_html_attribute($sCleanDesc) . '" />';

}

// ==========================================
// Canonical URL
// ==========================================
if (!empty($this->aPage['url'])) {
$sRet .= '';
}

// ==========================================
// Dynamic og:type detection
// ==========================================
$sUri = bx_get('i') ?: (isset($_GET['i']) ? $_GET['i'] : '');
$ogType = 'website'; // default

if (strpos($sUri, 'view-video') !== false) {
$ogType = 'video.other';
} elseif (strpos($sUri, 'view-publication') !== false) {
$ogType = 'article';
} elseif (strpos($sUri, 'view-event') !== false) {
$ogType = 'event';
} elseif (strpos($sUri, 'view-space-profile') !== false) {
$ogType = 'profile';
} elseif (strpos($sUri, 'view-organization-profile') !== false) {
$ogType = 'profile';
} elseif (strpos($sUri, 'view-group-profile') !== false) {
$ogType = 'profile';
} elseif (strpos($sUri, 'view-band-profile') !== false) {
$ogType = 'profile';
} elseif (strpos($sUri, 'view-course') !== false) {
$ogType = 'article';
} elseif (strpos($sUri, 'view-album') !== false) {
$ogType = 'album';
} elseif (strpos($sUri, 'view-channel') !== false) {
$ogType = 'video.other';
} elseif (strpos($sUri, 'view-photo') !== false) {
$ogType = 'image';
} elseif (strpos($sUri, 'view-discussion') !== false) {
$ogType = 'article';
} elseif (strpos($sUri, 'view-faq') !== false) {
$ogType = 'article';
} elseif (strpos($sUri, 'view-ad') !== false) {
$ogType = 'product';
}

$sRet .= '';
`

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions