HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //tmp/dateweb-usePageMeta.ts
import { useEffect } from 'react';

type PageMetaOptions = {
  canonical?: string;
  ogTitle?: string;
  ogDescription?: string;
  ogImage?: string;
  twitterImage?: string;
  jsonLd?: Record<string, unknown>;
  noIndex?: boolean;
};

function ensureMeta(selector: string, attribute: string, value: string) {
  const tag = document.querySelector(selector) || document.createElement('meta');
  tag.setAttribute(attribute, value);
  if (!tag.parentElement) {
    document.head.appendChild(tag);
  }
}

function ensureLink(rel: string, href: string) {
  const tag = document.querySelector('link[rel="' + rel + '"]') || document.createElement('link');
  tag.setAttribute('rel', rel);
  tag.setAttribute('href', href);
  if (!tag.parentElement) {
    document.head.appendChild(tag);
  }
}

export function usePageMeta(title: string, description: string, options: PageMetaOptions = {}) {
  useEffect(() => {
    document.title = title;

    ensureMeta('meta[name="description"]', 'content', description);

    const canonicalUrl = options.canonical || (window.location.origin + window.location.pathname);
    ensureLink('canonical', canonicalUrl);

    const jsonLdPayload = options.jsonLd ? JSON.stringify(options.jsonLd) : '';
    const ogTitle = options.ogTitle || title;
    const ogDescription = options.ogDescription || description;
    const ogImage = options.ogImage || '/media/generated/story-terrace-evening.webp';
    const twitterImage = options.twitterImage || ogImage;

    ensureMeta('meta[property="og:title"]', 'content', ogTitle);
    ensureMeta('meta[property="og:description"]', 'content', ogDescription);
    ensureMeta('meta[property="og:type"]', 'content', 'website');
    ensureMeta('meta[property="og:image"]', 'content', ogImage);
    ensureMeta('meta[property="og:url"]', 'content', canonicalUrl);
    ensureMeta('meta[name="twitter:card"]', 'content', 'summary_large_image');
    ensureMeta('meta[name="twitter:title"]', 'content', ogTitle);
    ensureMeta('meta[name="twitter:description"]', 'content', ogDescription);
    ensureMeta('meta[name="twitter:image"]', 'content', twitterImage);

    const robotsTag = document.querySelector('meta[name="robots"]') || document.createElement('meta');
    robotsTag.setAttribute('name', 'robots');
    robotsTag.setAttribute('content', options.noIndex ? 'noindex, nofollow' : 'index, follow');
    if (!robotsTag.parentElement) {
      document.head.appendChild(robotsTag);
    }

    const existingJsonLd = document.querySelector('script[data-dateweb-json-ld="1"]');
    if (jsonLdPayload) {
      if (existingJsonLd) {
        existingJsonLd.textContent = jsonLdPayload;
      } else {
        const jsonLdTag = document.createElement('script');
        jsonLdTag.type = 'application/ld+json';
        jsonLdTag.dataset.datewebJsonLd = '1';
        jsonLdTag.textContent = jsonLdPayload;
        document.head.appendChild(jsonLdTag);
      }
    } else if (existingJsonLd) {
      existingJsonLd.remove();
    }
  }, [
    title,
    description,
    options.canonical,
    options.ogTitle,
    options.ogDescription,
    options.ogImage,
    options.twitterImage,
    options.noIndex,
    options.jsonLd ? JSON.stringify(options.jsonLd) : '',
  ]);
}