/** * 構造化データ (Schema.org) ビルダーヘルパー * * 動画データから VideoObject の連想配列を組み立てる共通処理。 * チャンネルトップ (channel-popular-list / channel-latest-list) と * 一覧ページ (channel-popular-videos / channel-videos) の両方で同一仕様を使う。 */ if ( ! function_exists( 'build_schema_video_object' ) ) { /** * 動画データ配列から Schema.org VideoObject 形式の連想配列を生成する。 * * @param array $video get_video_data() / get_channel_cache_data() で取得した動画データ * @param string $channel_id 親チャンネル ID (URL 組み立て用) * * @return array|null video_id が空なら null */ function build_schema_video_object( $video, $channel_id ) { if ( empty( $video['video_id'] ) ) { return null; } $desc_parts = array(); $desc_parts[] = '再生回数' . number_format( $video['video_view'] ) . '回'; $desc_parts[] = 'いいね' . number_format( $video['video_like'] ) . '件'; $desc_parts[] = 'コメント' . number_format( $video['video_comment'] ) . '件'; if ( ! empty( $video['video_published_at'] ) ) { $desc_parts[] = '投稿日' . date( 'Y/m/d', $video['video_published_at'] ); } // Duration: 6-digit HHMMSS → ISO 8601 $iso_duration = ''; if ( ! empty( $video['video_duration'] ) ) { $dur = sprintf( '%06d', $video['video_duration'] ); $h = (int) substr( $dur, 0, 2 ); $m = (int) substr( $dur, 2, 2 ); $s = (int) substr( $dur, 4, 2 ); $iso_duration = 'PT'; if ( $h > 0 ) { $iso_duration .= $h . 'H'; } if ( $m > 0 ) { $iso_duration .= $m . 'M'; } $iso_duration .= $s . 'S'; } $item_data = array( '@type' => 'VideoObject', 'name' => $video['video_title'], 'url' => 'https://digitalcreators.jp/channel/' . $channel_id . '/videos/' . $video['video_id'] . '/', 'thumbnailUrl' => 'https://img.youtube.com/vi/' . $video['video_id'] . '/maxresdefault.jpg', 'embedUrl' => 'https://www.youtube.com/embed/' . $video['video_id'], 'description' => implode( '、', $desc_parts ), 'interactionStatistic' => array( array( '@type' => 'InteractionCounter', 'interactionType' => array( '@type' => 'WatchAction' ), 'userInteractionCount' => (int) $video['video_view'], ), array( '@type' => 'InteractionCounter', 'interactionType' => array( '@type' => 'LikeAction' ), 'userInteractionCount' => (int) $video['video_like'], ), array( '@type' => 'InteractionCounter', 'interactionType' => array( '@type' => 'CommentAction' ), 'userInteractionCount' => (int) $video['video_comment'], ), ), ); if ( ! empty( $iso_duration ) ) { $item_data['duration'] = $iso_duration; } if ( ! empty( $video['video_published_at'] ) ) { $item_data['uploadDate'] = date( "Y-m-d\TH:i:s+09:00", (int) $video['video_published_at'] ); } return $item_data; } } if ( ! function_exists( 'build_channel_additional_properties' ) ) { /** * チャンネルの統計値を Schema.org additionalProperty (PropertyValue の配列) として生成する。 * チャンネルランキング(カルーセルの各ListItem)とチャンネルページ(ProfilePage の mainEntity)で共用。 * * @param array $c チャンネルデータ連想配列。channel_ranking.JP の行 / get_channel_data() の結果。 * 必要列: channel_difference_user, channel_difference_view, channel_video_view, * channel_user, channel_newest_avg_view_count, channel_newest_avg_good, * channel_newest_avg_comment, channel_newest_per_engagement。 * * @return array PropertyValue 連想配列のリスト(該当データが無い項目はスキップ)。 */ function build_channel_additional_properties( $c ) { // label => array( 列名, 値の型 )。値は表示中の項目に対応。 $map = array( '30-Day Subscriber Growth' => array( 'channel_difference_user', 'int' ), '30-Day View Count Growth' => array( 'channel_difference_view', 'int' ), 'Lifetime Channel Views' => array( 'channel_video_view', 'int' ), 'Total Channel Subscribers' => array( 'channel_user', 'int' ), 'Average Views Per Video' => array( 'channel_newest_avg_view_count', 'round' ), 'Average Likes Per Video' => array( 'channel_newest_avg_good', 'round' ), 'Average Comments Per Video' => array( 'channel_newest_avg_comment', 'round' ), 'Channel Engagement Rate' => array( 'channel_newest_per_engagement', 'rate' ), ); $props = array(); foreach ( $map as $label => $def ) { list( $col, $type ) = $def; if ( ! isset( $c[ $col ] ) || $c[ $col ] === '' || $c[ $col ] === null ) { continue; } $raw = $c[ $col ]; if ( $type === 'rate' ) { // engagement率: 保存値は比率(0.0615)なので %(6.15) に変換し unitText を付与。 $props[] = array( '@type' => 'PropertyValue', 'name' => $label, 'value' => round( (float) $raw * 100, 2 ), 'unitText' => 'PERCENT', ); continue; } $value = ( $type === 'round' ) ? (int) round( (float) $raw ) : (int) $raw; $props[] = array( '@type' => 'PropertyValue', 'name' => $label, 'value' => $value, ); } return $props; } } CapcomChannel | YouTuberトレンド分析メディア:デジタルクリエイターズ

CapcomChannel

新着記事

CapcomChannelのトレンドニュース