WP CSS

動画の構造化データ・mRSS・video sitemap の自動生成

動画の構造化データ・mRSS・video sitemap の自動生成 は。Search Console 動画がメインコンテンツでない時の対処法です。

Sponsor

Search Console 動画がメインコンテンツでない時の対処法

「動画がメインコンテンツでない」とSearch Consoleで動画がインデックスされない場合があります。

動画がメインコンテンツと見なされるために必要なこと

  • スクロールせず、見える範囲に動画が表示されていること
  • 動画を視聴することがページの目的であること

次の場合は、動画がメインコンテンツとみなされず、動画がインデックスされない可能性があります。

  • 動画がページの主なコンテンツではなくテキストを補完するものであるブログ投稿
  • 補完的な動画を含む商品の詳細ページ
  • 複数の動画を同等の視認性で一覧表示している動画カテゴリページ

ページはインデックスされてるが動画がメインコンテンツでなければインデックスされない。

動画がメインコンテンツでなければインデックスされない/Search Console
Sponsor

Googleの動画検索にインデックスされやすくする

記事の抜粋は100文字程度

記事の抜粋

  • 先頭に検索キーワードを入れる
  • 「動画」という要素を文章中に含める
  • 動画の内容(主題・場所・登場人物など)を明確にする

「このページには動画がありますよ」と明確に伝えることが大事で、Search Consoleの「動画ページ」のインデックスのせるための構造化データを追加する必要があります。

Sponsor

動画の構造化データ・mRSSフィード・video-sitemap

「動画サイトマップ」または「 MRSSフィード」を作成して、Googleに動画情報を明確に認識させます。

動画をインデックスさせるには、動画サイトマップまたはMRSSフィードを送信してください。

gooogle

インデックスさせるために、次の3つの方法で動画コンテンツであることをGoogleに伝えます。

  • 動画の構造化データ Googleに動画の情報を伝える
  • video sitemap Googleにサイトに動画コンテンツがあることを知らせる
  • mRSSフィード 動画コンテンツがあることを伝える
構造化データ各記事の <head> に自動挿入Google検出
mRSSフィードmrss.xml など更新情報を届ける
video-sitemapvideo-sitemap.xml などSearch Console登録
サイトマップsitemap.xml などSearch Console登録

※yoast のサイトマップはhttps://ドメイン/sitemap_index.xml

「video-sitemap」「mRSSフィード」でGoogle・検索エンジンに動画があることを伝え、「構造化データ」で動画の必要項目を伝えます。

Sponsor

コードを貼った後に動作確認する方法

「video-sitemap」「mRSSフィード」「構造化データ」の自動生成コードを functions.php などに記述しますが、記述後の動作確認の方法は以下の通りです。

確認する場所確認
構造化データ動画投稿ページ<head>VideoObject を確認
mRSSフィード/video-feed/ <rss> が表示される
動画サイトマップ/video-sitemap.xml<sitemapindex> が表示される

※mRSSフィードのURLは /video-feed/ や /?feed=mrss 動画サイトマップは /video-sitemap.xml ですがコードの記述によって、URLは変わります。

下記の「video-sitemapとmRSSフィードのコード」では次の通り設定しています。

  • Video Sitemap のURL https://○○○/video-map.xml
  • mRSS Feed のURL https://○○○/’video-mrss.xml

構造化データ生成コードやmRSSフィード・video-sitemap 生成コードを貼った後に、コードの動作確認します。その手順を先に説明しておきます。

構造化データテストとリッチザルトテスト

VideoObject (動画の構造化データ)を確認します。

テストテストするURL
リッチザルトテストサイトのURL
構造化データテスト動画がある投稿のURL

リッチザルトテスト・構造化データテストの結果

  • VideoObject(動画の構造化データ)がマークアップされてい

リッチザルトテスト

リッチザルトテスト

構造化データテスト

構造化データテスト

動画投稿ページ<head>

  1. 動画のあるページを右クリック
  2. ページのソースを表示
  3. VideoObjectを確認する
動画投稿ページ内の構造化データの確認

この結果で、記述するコードが問題なく動いていることがわかります。

mRSSフィード の動作確認

mRSSフィード は、世の中に動画や画像などメディアコンテンツがあることを発信するFeedで、動画サイトマップの代替手段にもなります。

  • 確認URL https://○○○/mrss.xml または https://○○○/?feed=mrss 、https://○○○/video-mrss.xmlなど

ページが表示され、動画コンテンツ が出力されている。(もし404の場合は下記のリトライルールを再生成をしてみて下さい)

video sitemap の動作確認

video sitemap を作り、Googleに動画のあるページであることを伝えます。

  • 確認URL https://○○○/video-sitemap.xml など

https://○○○/video-sitemap.xml でXMLが生成されるか確認する。(もし404の場合は下記のリトライルールを再生成をしてみて下さい)

<sitemapindex> が表示される

動画サイトマップ

サイトマップのURLは記述により変えることができます。必ずしも video-sitemap.xml ではない。

video sitemap や mRSSフィード の登録

video sitemap や mRSSフィード を自動生成後に、そのURLを以下に登録します。

video sitemapGoogle Search Console へ登録する
https://search.google.com/search-console
mRSSフィードBing Webmaster Tools へ登録する
https://www.bing.com/webmasters
Sponsor

video sitemap や mRSSフィード にアクセスして404になる場合

video sitemap や mRSSフィード の確認で404になる場合の対処法です。

  • https://ドメイン/video-sitemap.xml →404になる
  • https://ドメイン/mrss.xml →404になる

404になる原因

  • リライトルールにより404となる

404を解消する手順(video sitemap や mRSSフィード の確認手順)

リトライルールを再生成する

  1. 管理画面 → 設定 → パーマリンク設定
  2. 何も変更せずに「変更を保存」をクリック
  3. リライトルールが再生成される
  4. 再度、video-feedmrss.xml にアクセスする
  5. video-feed mrss.xml が表示される
Sponsor

Search Consoleに登録するサイトマップのURLについて

Google Search Consoleに登録するサイトマップのURLの例

  • https://○○○/video-sitemap.xml

もしサイトマップを分割した場合

  • https://〇〇〇/video-sitemap-1.xml
  • https://○○○/video-sitemap-2.xml

この場合はもGoogle Search Consoleに登録するサイトマップのURLは

  • https://○○○/video-sitemap.xml

サイトマップのURLは記述により変えることができます。必ずしも video-sitemap.xml ではない。

Sponsor

構造化データで動画をマークアップする

Webページの構造を検索エンジン(Google)により分かりやすく伝えるためにHTMLにマークアップするコードを「構造化データ」と言います。

動画に、JSON-LD形式でVideoObject構造化データを挿入すること。

参考:Google Search Central

Google の VideoObject 構造化データに必要な要素

  • 構造化データ 各記事の<head>に自動挿入

動画をマークアップするのに必要な情報(構造化データ)

構造化データのマークアップの例

<script type=”application/ld+json”>
{
“@context”: “http://schema.org”,
“@type”: “VideoObject”,
“name”: “動画のタイトル”, 
“description”: “動画の説明”,
“thumbnailUrl”: “http://img.youtube.com/〇〇〇.jpg   /*動画のサムネイル*/ ”,
“uploadDate”: “2025-2-23T18:00:00+09:00   /*動画の公開日時*/ ”,
“duration”: “PT00H00M40S   /*動画の長さ*/ ”,
“contentUrl”: “https://youtube.com/〇〇〇”,
“embedUrl”: “”,
“interactionStatistic”:: {
        "@type": "InteractionCounter",
        "interactionType": { "@type": "WatchAction" },
        "userInteractionCount": 100   /*動画の視聴回数*/      },
}
</script>
name動画のタイトル(記事タイトルでも可)
description動画の説明
thumbnailUrl動画のサムネイルURL
uploadDate動画の公開日時
duration動画の再生時間 PT00H00M40S(ISO 8601形式)
contentUrlhttps://youtube.com/〇〇〇(Youtube等)
embedUrlcontentUrl を使用できない場合 embedUrl を指定
https://youtube.com/embed/○○〇
Sponsor

動画構造化データ(VideoObject)を自動出力するコード①

このコードでできること

  • 動画構造化データ 各投稿ページの <head> にJSON-LD形式でVideoObjectを自動挿入(動画がある投稿のみ)
  • 自動サムネイル YouTube API不要(img.youtube.com 利用)
  • ショート動画を含む動画

functions.php に追加する<head>内に自動挿入される

// YouTube動画とショート動画の構造化データ 
add_action('wp_head', function() {
    if (!is_single()) return;

    global $post;
    $content = $post->post_content;

 // YouTube埋め込みURLを抽出
    if (!preg_match('/https?:\/\/(?:www\.)?(?:youtube\.com|youtu\.be)\/[^\s"\'<>]+/', $content, $match)) return;
    $url = $match[0];

 // 動画ID抽出
    if (preg_match('/(?:v=|youtu\.be\/)([A-Za-z0-9_-]+)/', $url, $id_match)) {
        $video_id = $id_match[1];
    } else return;

// サムネイルURL
    $thumbnail = "https://img.youtube.com/vi/{$video_id}/maxresdefault.jpg";
// サムネが存在しない場合 fallback
    $headers = @get_headers($thumbnail);
    if (!$headers || strpos($headers[0], '404') !== false) {
        $thumbnail = "https://img.youtube.com/vi/{$video_id}/hqdefault.jpg";
    }
// それでも404なら代替画像
    $headers = @get_headers($thumbnail);
    if (!$headers || strpos($headers[0], '404') !== false) {
        $thumbnail = get_template_directory_uri() . '/no-thumbnail.jpg';
    }

 // duration の自動生成
    // URL内に「shorts」が含まれていれば 59秒(PT59S)として扱う
    $duration = (strpos($url, 'shorts') !== false) ? 'PT59S' : 'PT3M00S'; // デフォ3分

 // 公開日と更新日
    $uploadDate = get_the_date('c', $post);
    $modDate = get_the_modified_date('c', $post);

 // VideoObject構造化データの出力
    $schema = [
        "@context" => "https://schema.org",
        "@type" => "VideoObject",
        "name" => get_the_title($post),
        "description" => wp_strip_all_tags(get_the_excerpt($post)),
        "thumbnailUrl" => [$thumbnail],
        "uploadDate" => $uploadDate,
        "dateModified" => $modDate,
        "contentUrl" => $url,
        "embedUrl" => $url,
        "duration" => $duration,
        "publisher" => [
            "@type" => "Organization",
            "name" => get_bloginfo('name'),
            "logo" => [
                "@type" => "ImageObject",
                "url" => get_site_icon_url()
            ]
        ]
    ];

    echo "\n<script type='application/ld+json'>" . wp_json_encode($schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . "</script>\n";
});
投稿・固定ページの
動画の構造化データ
add_action('wp_head', function() {
if (!is_single()) return;
global $post;
$content = $post->post_content;
動画のURL抽出 if (!preg_match('/https?:\/\/(?:www\.)?(?:
動画ID抽出 if (preg_match('/(?:v=|youtu\.be\/)([A-Za-z0-9_-]+)/', $url, $id
サムネURL/maxresdefault.jpg
サムネがない場合/hqdefault.jpg
404の代替画像/no-thumbnail.jpg
durationPT3M00S
shortsならば59秒(strpos($url, 'shorts') !== false) ? 'PT59S'
公開日更新日get_the_date('c', $post)
get_the_modified_date('c', $post)
Sponsor

動画のサムネと時間・タイトルを取得するコード ①

構造化データにはサムネイルと動画の再生時間が必要です。ショート動画はサムネがありません。次のコードではYouTube API を使わず、サムネイルを自動で取得できます。

  • 自動サムネイル YouTube API不要(img.youtube.com 利用)
  • YouTube動画とショート動画の構造化データ生成
  • YouTube APIを使わずにサムネイルと動画時間を自動取得
  • サムネイルは自動生成(存在しない場合は no-thumbnail.jpg 等で代替)
  • duration(動画長)を自動生成(ショート=60秒未満)
  • 投稿日 uploadDate に記事公開日を自動挿入

functions.php

// YouTube動画・ショート動画の構造化データ生成
add_action('wp_head', function() {
  if (is_single()) {
    global $post;

// YouTube埋め込みURLを本文から取得
    if (preg_match('/youtube\.com\/embed\/([a-zA-Z0-9_-]+)/', $post->post_content, $matches)) {
      $video_id = $matches[1];
      $title = esc_attr(get_the_title($post->ID));
      $url = get_permalink($post->ID);
      $uploadDate = get_the_date('c', $post->ID);
      $desc = wp_strip_all_tags(get_the_excerpt($post->ID));

// サムネイルを最大 → hqdefault → デフォルト画像の順でチェック
      $thumb_candidates = [
        "https://img.youtube.com/vi/{$video_id}/maxresdefault.jpg",
        "https://img.youtube.com/vi/{$video_id}/hqdefault.jpg",
        "https://img.youtube.com/vi/{$video_id}/default.jpg",
      ];
      $thumb = '';
      foreach ($thumb_candidates as $t) {
        $headers = @get_headers($t);
        if ($headers && strpos($headers[0], '200') !== false) {
          $thumb = $t;
          break;
        }
      }
      if (!$thumb) {
 // サムネが存在しない場合のバックアップ画像(サイトロゴなど)
        $thumb = get_site_icon_url() ?: 'https://via.placeholder.com/480x360?text=No+Thumbnail';
      }

// duration(時間)を自動生成
 // → "shorts"(ショート動画) とタイトル・URLを検出したら 60秒以内とみなす
      if (strpos($post->post_content, '/shorts/') !== false || stripos($title, 'short') !== false) {
        $duration = 'PT60S'; // ショート動画(最大1分)
      } else {
        $duration = 'PT180S'; // 通常動画(3分)
      }
サムネイル自動取得maxresdefault → hqdefault → default の順にチェック
duration(再生時間)/shorts/ や YouTubeショートURLを自動検出し
durationをPT59Sに設定

duration(再生時間)の表示(時間を書き換える)

30秒PT30S
5分PT5M00S

通常のYouTube動画とショート動画のコード

//Youtube動画
if (preg_match('/https?:\/\/(?:www\.)?(?:youtube\.com\/watch\?v=|youtu\.be\/)([A-Za-z0-9_-]+)/', $content, $m)) {

//Youtubeショート動画
if (preg_match('/https?:\/\/(?:www\.)?(?:youtube\.com\/(?:watch\?v=|shorts\/)|youtu\.be\/)([A-Za-z0-9_-]+)/', $content, $m)) {
Sponsor

動画構造化データ(VideoObject)を自動出力するコード②

このコードでできること

  • 動画構造化データ 各投稿ページの <footer> にJSON-LD形式でVideoObjectを自動挿入(動画がある投稿のみ)
  • 自動サムネイル YouTube API不要(img.youtube.com 利用)
  • ショート動画を含む動画

テーマ:cocoon

functions.php に追加する<footer>内に自動挿入される

※example.comはサイトのドメインに変更

// YouTube動画構造化データ自動出力

function cocoon_add_videoobject_jsonld() {
    if (is_single()) {
        global $post;
        $content = $post->post_content;

        // YouTube動画を検出(iframe で埋め込んでる場合)
        if (preg_match('/youtube\.com\/embed\/([a-zA-Z0-9_-]+)/', $content, $matches)) {
            $video_id = $matches[1];
            $title = get_the_title();
            $description = wp_strip_all_tags(get_the_excerpt());
            $thumbnail = "https://i.ytimg.com/vi/{$video_id}/hqdefault.jpg";
            $upload_date = get_the_date('c');
            $publisher_name = get_bloginfo('name');
            $publisher_logo = 'https://example.com/wp-content/uploads/logo.png'; // ← サイトのロゴURL

            $videoobject = [
                "@context" => "https://schema.org",
                "@type" => "VideoObject",
                "name" => $title,
                "description" => $description,
                "thumbnailUrl" => [$thumbnail],
                "uploadDate" => $upload_date,
                "embedUrl" => "https://www.youtube.com/embed/{$video_id}",
                "contentUrl" => "https://www.youtube.com/watch?v={$video_id}",
                "publisher" => [
                    "@type" => "Organization",
                    "name" => $publisher_name,
                    "logo" => [
                        "@type" => "ImageObject",
                        "url" => $publisher_logo
                    ]
                ]
            ];

            echo '<script type="application/ld+json">' .
                 wp_json_encode($videoobject, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) .
                 '</script>';
        }
    }
}
add_action('wp_footer', 'cocoon_add_videoobject_jsonld');

コードを追加した後の動作確認

「VideoObject(動画)」が検出される。

/**
 *  完全版 YouTube VideoObject 自動生成(ショート動画対応)
 * - パラメータ付き embed URL でも100%動画IDを抽出
 * - 重複URLなし(Googleインデックス最適化)
 * - oEmbed API で動画情報取得
 */
function perfect_videoobject_single() {

    if (!is_single()) return;

    global $post;
    $content = $post->post_content;

    //  パラメータ付き embed URL に完全対応
    if (!preg_match('/youtube\.com\/embed\/([a-zA-Z0-9_-]+)(?=[\?"]|$)/', $content, $matches)) {
        return; // 動画がない投稿はスキップ
    }

    $video_id = $matches[1];
    $youtube_url = "https://www.youtube.com/watch?v={$video_id}";
    $embed_url   = "https://www.youtube.com/embed/{$video_id}";

    //  oEmbed で動画情報取得
    $oembed_api = "https://www.youtube.com/oembed?url=" . urlencode($youtube_url) . "&format=json";
    $response = wp_remote_get($oembed_api, ['timeout' => 5]);

    if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) == 200) {
        $oembed = json_decode(wp_remote_retrieve_body($response), true);

        $title = $oembed['title'] ?? get_the_title();
        $thumbnail = $oembed['thumbnail_url'] ?? "https://i.ytimg.com/vi/{$video_id}/hqdefault.jpg";
        $description = wp_strip_all_tags(get_the_excerpt());

    } else {
        $title = get_the_title();
        $thumbnail = "https://i.ytimg.com/vi/{$video_id}/hqdefault.jpg";
        $description = wp_strip_all_tags(get_the_excerpt());
    }

    //  Shorts / 縦動画判定(高さ > 横)
    $duration = 'PT2M';
    if (preg_match('/height="([0-9]+)".*width="([0-9]+)"/', $content, $dims)) {
        if ($dims[1] > $dims[2]) $duration = 'PT1M';
    }

    $upload_date = get_the_date('c');
    $publisher_name = get_bloginfo('name');
    $publisher_logo = get_site_icon_url();

    //  VideoObject(Google最適化版)
    $videoobject = [
        "@context"  => "https://schema.org",
        "@type"     => "VideoObject",
        "name"      => $title,
        "description" => $description,
        "thumbnailUrl" => [$thumbnail],
        "uploadDate" => $upload_date,
        "duration"   => $duration,

        //  Google推奨:URLを1個に統一(重複なし)
        "embedUrl"  => $embed_url,
        "contentUrl" => $youtube_url,
        "url"        => get_permalink(),

        "inLanguage" => "ja",
        "publisher" => [
            "@type" => "Organization",
            "name"  => $publisher_name,
            "logo"  => [
                "@type" => "ImageObject",
                "url"   => $publisher_logo
            ]
        ]
    ];

    echo '<script type="application/ld+json">' .
        wp_json_encode($videoobject, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) .
        '</script>';
}
add_action('wp_footer', 'perfect_videoobject_single');


/**
 *  トップページ:最新3動画を VideoObject 化
 */function perfect_videoobject_home() {

    if (!is_front_page()) return;

    $query = new WP_Query([
        'post_type' => 'post',
        'posts_per_page' => 3,
        'post_status' => 'publish'
    ]);

    $videos = [];

    while ($query->have_posts()) {
        $query->the_post();

        if (preg_match('/youtube\.com\/embed\/([a-zA-Z0-9_-]+)(?=[\?"]|$)/', get_the_content(), $m)) {

            $video_id = $m[1];
            $youtube_url = "https://www.youtube.com/watch?v={$video_id}";
            $embed_url   = "https://www.youtube.com/embed/{$video_id}";

            // oEmbed取得
            $oembed_api = "https://www.youtube.com/oembed?url=" . urlencode($youtube_url) . "&format=json";
            $response = wp_remote_get($oembed_api, ['timeout' => 5]);

            if (!is_wp_error($response) && wp_remote_retrieve_response_code($response) == 200) {
                $oembed = json_decode(wp_remote_retrieve_body($response), true);

                $title = $oembed['title'] ?? get_the_title();
                $thumbnail = $oembed['thumbnail_url'] ?? "https://i.ytimg.com/vi/{$video_id}/hqdefault.jpg";
                $description = wp_strip_all_tags(get_the_excerpt());

            } else {
                $title = get_the_title();
                $thumbnail = "https://i.ytimg.com/vi/{$video_id}/hqdefault.jpg";
                $description = wp_strip_all_tags(get_the_excerpt());
            }

            $videos[] = [
                "@context" => "https://schema.org",
                "@type" => "VideoObject",
                "name" => $title,
                "description" => $description,
                "thumbnailUrl" => [$thumbnail],
                "uploadDate" => get_the_date('c'),
                "duration" => "PT1M30S",
                "embedUrl" => $embed_url,
                "contentUrl" => $youtube_url,
                "url" => get_permalink(),
                "inLanguage" => "ja",
                "publisher" => [
                    "@type" => "Organization",
                    "name" => get_bloginfo('name'),
                    "logo" => [
                        "@type" => "ImageObject",
                        "url" => get_site_icon_url()
                    ]
                ]
            ];
        }
    }

    wp_reset_postdata();

    if ($videos) {
        echo '<script type="application/ld+json">' .
            wp_json_encode($videos, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT) .
            '</script>';
    }
}
add_action('wp_head', 'perfect_videoobject_home');


/**
 *  LazyLoad 除外(CLS対策)
 */function perfect_lazyload_exclude() {
    if (class_exists('LiteSpeed_Cache_API')) {
        LiteSpeed_Cache_API::config([
            'lazyload_img_excludes' => '.youtube, .video-container, .video',
            'lazyload_iframe_excludes' => '.youtube, .video-container, .video',
        ]);
    }
}
add_action('init', 'perfect_lazyload_exclude');
Sponsor

Video Sitemap・mRSSフィード自動生成

機能効果
VideoObject構造化データ検索結果で動画リッチリザルト表示
Video SitemapGoogle動画検索等に掲載されやすくなる
mRSS Feed検索エンジン最適化

このコードでできること

  • Video Sitemap自動生成
  • mRSSフィード自動生成(動画RSS)

【重要】

  • Video Sitemap のURL https://○○○/video-map.xml
  • mRSS Feed のURL https://○○○/’video-mrss.xml

下のソースの「// URLルールを追加」で変更可能。「video-sitemap.xml」で404エラーとなったために「video_sitemap.xml」にする。

// URLルールを追加
function add_custom_video_feeds() {
    add_rewrite_rule('video-map\.xml$', 'index.php?video_sitemap=1', 'top');
    add_rewrite_rule('video-mrss\.xml$', 'index.php?video_mrss=1', 'top');
}

functions.php に追加する

// Video Sitemap と mRSS Feed 自動生成

//  YouTube ID 抽出関数
function extract_youtube_id_from_post($content) {
    if (preg_match('/youtube\.com\/embed\/([a-zA-Z0-9_-]+)/', $content, $matches)) {
        return $matches[1];
    }
    return false;
}

//  動画サイトマップ出力
function generate_video_sitemap() {
    $output = '<?xml version="1.0" encoding="UTF-8"?>';
    $output .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
                 xmlns:video="http://www.google.com/schemas/sitemap-video/1.1">';

    $query = new WP_Query([
        'post_type' => 'post',
        'post_status' => 'publish',
        'posts_per_page' => 1000,
    ]);

    while ($query->have_posts()) {
        $query->the_post();
        $video_id = extract_youtube_id_from_post(get_the_content());
        if ($video_id) {
            $url = esc_url(get_permalink());
            //  HTML実体参照をUTF-8文字に変換してからエスケープ
            $title = esc_html( html_entity_decode( get_the_title(), ENT_QUOTES, 'UTF-8' ) );
            $desc = esc_html( html_entity_decode( wp_strip_all_tags( get_the_excerpt() ), ENT_QUOTES, 'UTF-8' ) );
            $thumbnail = esc_url("https://i.ytimg.com/vi/{$video_id}/hqdefault.jpg");
            $embed = esc_url("https://www.youtube.com/embed/{$video_id}");
            $pub = get_the_date('c');

            $output .= "<url>";
            $output .= "<loc>{$url}</loc>";
            $output .= "<video:video>";
            $output .= "<video:thumbnail_loc>{$thumbnail}</video:thumbnail_loc>";
            $output .= "<video:title>{$title}</video:title>";
            $output .= "<video:description>{$desc}</video:description>";
            $output .= "<video:player_loc allow_embed='yes'>{$embed}</video:player_loc>";
            $output .= "<video:publication_date>{$pub}</video:publication_date>";
            $output .= "<video:family_friendly>yes</video:family_friendly>";
            $output .= "</video:video>";
            $output .= "</url>";
        }
    }
    wp_reset_postdata();

    $output .= '</urlset>';
    return $output;
}

//  mRSS出力(動画RSSフィード)
function generate_video_mrss() {
    $output = '<?xml version="1.0" encoding="UTF-8"?>';
    $output .= '<rss version="2.0" xmlns:media="http://search.yahoo.com/mrss/">';
    $output .= '<channel>';
    $output .= '<title>' . esc_html( get_bloginfo('name') . ' - Video Feed' ) . '</title>';
    $output .= '<link>' . esc_url( home_url() ) . '</link>';
    $output .= '<description>Video feed generated from posts with YouTube embeds.</description>';

    $query = new WP_Query([
        'post_type' => 'post',
        'post_status' => 'publish',
        'posts_per_page' => 1000,
    ]);

    while ($query->have_posts()) {
        $query->the_post();
        $video_id = extract_youtube_id_from_post(get_the_content());
        if ($video_id) {
            $url = esc_url(get_permalink());
            $title = esc_html( html_entity_decode( get_the_title(), ENT_QUOTES, 'UTF-8' ) );
            $desc = esc_html( html_entity_decode( wp_strip_all_tags( get_the_excerpt() ), ENT_QUOTES, 'UTF-8' ) );
            $thumb = esc_url("https://i.ytimg.com/vi/{$video_id}/hqdefault.jpg");
            $video = esc_url("https://www.youtube.com/watch?v={$video_id}");
            $pub = get_the_date('r');

            $output .= "<item>";
            $output .= "<title>{$title}</title>";
            $output .= "<link>{$url}</link>";
            $output .= "<description>{$desc}</description>";
            $output .= "<media:thumbnail url='{$thumb}' />";
            $output .= "<media:content url='{$video}' medium='video' />";
            $output .= "<pubDate>{$pub}</pubDate>";
            $output .= "</item>";
        }
    }

    wp_reset_postdata();
    $output .= '</channel></rss>';
    return $output;
}

// URLルールを追加
function add_custom_video_feeds() {
    add_rewrite_rule('video-map\.xml$', 'index.php?video_sitemap=1', 'top');
    add_rewrite_rule('video-mrss\.xml$', 'index.php?video_mrss=1', 'top');
}
add_action('init', 'add_custom_video_feeds');

// クエリ変数登録
function add_custom_video_query_vars($vars) {
    $vars[] = 'video_sitemap';
    $vars[] = 'video_mrss';
    return $vars;
}
add_filter('query_vars', 'add_custom_video_query_vars');

//  XML出力(テンプレートルート)
function custom_video_template_redirect() {
    if (get_query_var('video_sitemap')) {
        header('Content-Type: application/xml; charset=UTF-8');
        echo generate_video_sitemap();
        exit;
    }
    if (get_query_var('video_mrss')) {
        header('Content-Type: application/rss+xml; charset=UTF-8');
        echo generate_video_mrss();
        exit;
    }
}
add_action('template_redirect', 'custom_video_template_redirect', 1);

Video Sitemap のURL と mRSS Feed のURL を変更する

Video Sitemap のURL と mRSS Feed のURL を変更する場合は、上記のコードの「// URLルールを追加」の部分を変更します。

【例】/video-sitemap.xml にする場合

add_rewrite_rule('video-sitemap\.xml$', 'index.php?video_sitemap=1', 'top');
Sponsor

YoutubeサムネイルURL取得について/ 動画がメインコンテンツ

  • humbnailUrl (サムネのURL)

YoutubeサムネイルURL取得サイト

“thumbnailUrl”: “http://img.youtube.com/vi/〇〇〇.jpg”, 
Sponsor

Youtube動画・ショート動画の公開日時を調べる

  • uploadDate (動画の公開日時)
“uploadDate”: “2025-2-23T18:00:00+09:00”, 

下の①②の手順で公開日時を知ることができます。

① DetailedTime

YouTube動画の公開時刻を表示する Google Chrome の拡張機能

  • 公開したYouTubeのタイトルの下に「詳細」の文字が表示され、「詳細」をクリックすると時刻が表示される

ショート動画の公開時間を調べる方法

ショート動画https://www.youtube.com/shorts/ONiK0ywYiI8
通常の表示https://youtube.com/watch?v=ONiK0ywYiI8
  • shorts/」を「watch?v=」に変更して表示する
  • YouTubeのタイトルの下に「詳細」の文字が表示され、「詳細」をクリックすると時刻(2025-2-23T18:00:00+09:00)が表示される

② 動画の公開日時をISO8601形式に変換する

DenCode (https://dencode.com/ja/date)を利用する

  • 上記「詳細」の時刻(2025/02/23 09:00)をコピぺ
  • エンコード結果 ISO8601形式(拡張)に「2025-2-23T18:00:00+09:00」と表示される
Sponsor

duration (動画の再生時間)

“duration”: “PT00H00M40S”, 
  • PT(時間)H(分)M(秒)で表示
  • 40秒は「PT00H00M40S」

動画のインデックス登録エラー「動画がビューポートの外側にあります」

YouTube ショート動画を縦長で表示する方法/サイズを合わせる方法

ゆきを

Recent Posts

動画一覧と動画をクリックすると投稿に飛ぶコード

動画一覧と動画をクリックすると…

2週間 ago

画像をぼかし文字を被せるCSS/アイチャッチの上にタイトル

画像をぼかし文字を被せる 画像…

4週間 ago

無料で使えるAIライティングツール 12選

AIライティングツールで何がで…

2か月 ago

upload_max_filesize のエラー WP

php.ini の uploa…

4か月 ago

PHPバージョンの変更手順 WP

WordPress で 推奨さ…

4か月 ago

1つ以上のモジュールが存在しませんの解決

サイトヘルスの致命的な問題 1…

4か月 ago