Store YouTube videos data from a playlist in WordPress

I’ve encountered a problem where I wanted to display the latest YouTube videos from several playlists on the website, without manually entering the data. The way to do that would be to pull the data using YouTube API; however, I didn’t want to call it on each page load so needed a way of caching the basic information in the database. Even though WordPress does provide transients for this purpose, in the past I’ve found them getting our of hand with the number of options created and removed, so I find it easier to simply store all the data in a single option – for 3-5 videos in a handful of playlists this is not a problem.

<?php

/**
 * Get video data from the database, or update the option
 *
 * @param int $playlist_id
 * @return array|false the playlist array or void
 */
function get_youtube_playlist_videos($playlist_id)
{
  $playlists = get_option('youtube_playlists');

  if (empty($playlists) || !array_key_exists($playlist_id, $playlists)) {
    $playlists = update_youtube_playlist_videos($playlist_id);
  }

  return array_key_exists($playlist_id, $playlists) ? $playlists[$playlist_id] : false;
}


/**
 * Populate the YouTube playlists option with video data
 *
 * @param integer $playlist_id
 * @return array|false the array of playlists or void
 */
function update_youtube_playlist_videos($playlist_id = 0)
{
  $playlists = get_option('youtube_playlists', []);

  // Insecure in a public repository – find a way to store separately
  $api_key = 'ENTER_API_KEY_HERE';
  $count = 1;
  $max_results = 5;
  $limit = 3;

  if (0 === $playlist_id) {
    if (empty($playlists)) return;

    foreach ($playlists as $playlist_id => $videos) {
      update_youtube_playlist_videos($playlist_id);
    }

    return;
  }

  $url = sprintf('https://www.googleapis.com/youtube/v3/playlistItems?key=%s&playlistId=%s&part=snippet&maxResults=%d', $api_key, $playlist_id, $max_results);

  $videos = json_decode(file_get_contents($url));

  if (empty($videos->items)) return;

  $videos_array = [];

  foreach ($videos->items as $video) {
    // Remove private videos – adjust the $max_results above to account for this
    if (0 === strpos($video->snippet->title, 'Private video')) continue;

    if ($count > $limit) break;

    // Only store the required data – change according to your needs
    $videos_array[$video->snippet->resourceId->videoId] = [
      'title' => $video->snippet->title,
      'date' => $video->snippet->publishedAt,
      'thumbnail' => $video->snippet->thumbnails->medium->url,
    ];

    $count++;
  }

  $playlists[$playlist_id] = $videos_array;

  // Store the videos data
  update_option('youtube_playlists', $playlists);

  return $playlists;
}


/**
 * Schedule an event
 */
if (!wp_next_scheduled('youtube_playlists')) {
  wp_schedule_event(time(), 'daily', 'youtube_playlists');
}
add_action('youtube_playlists', 'update_youtube_playlist_videos');

Then in a shortcode:

function youtube_videos_shortcode($atts, $content, $shortcode)
{
  ob_start();

  if (!$atts['playlist']) return;

  $videos = get_youtube_playlist_videos($atts['playlist']);

  if (empty($videos) || !is_array($videos)) return;

  foreach ($videos as $video_id => $video) {
    $url = 'https://www.youtube.com/watch?v=' . $video_id;

    // Shortcode template here
  }

  return ob_get_clean();
}
add_shortcode('youtube-videos', 'youtube_videos_shortcode');

Usage:

[youtube-videos playlist="PLAYLIST_ID"]

Leave a Reply

Your email address will not be published. Required fields are marked *