Usage
nebula()->video_meta($provider, $id)
Parameters
$provider
(Required) (String) Which video service to check
Default: None
$id
(Required) (String) The ID of the video to get metadata for
Default: None
Examples
Trackable Youtube video iframe
<?php $youtube_data = nebula()->video_meta('youtube', 'gCWaRhNUvfc'); ?>
<div class="embed-responsive embed-responsive-16by9">
<iframe id="<?php echo $youtube_data['id']; ?>" class="youtube embed-responsive-item" width="560" height="315" title="<?php echo $youtube_data['title']; ?>" src="//www.youtube.com/embed/<?php echo $youtube_data['id']; ?>?wmode=transparent&enablejsapi=1&rel=0" allow="autoplay"></iframe>
</div>
Trackable Vimeo video iframe
<?php $vimeo_data = nebula()->video_meta('vimeo', '208432684'); ?>
<div class="embed-responsive embed-responsive-16by9">
<iframe id="<?php echo $vimeo_data['id']; ?>" class="vimeo embed-responsive-item" src="https://player.vimeo.com/video/<?php echo $vimeo_data['id']; ?>" width="560" height="315"></iframe>
</div>
Demo
Youtube
See nebulaYoutubeTracking() for available Nebula data for Youtube videos.
Note: the enablejsapi=1 query parameter is needed for tracking to work. Nebula adds it automatically, but it is significantly faster to include it manually.
Note: it is recommended to use a title attribute on the iframe to enhance analytics reports with a video title (rather than a video ID).
Note: iframes can be lazy loaded with either hard-coded HTML (nebula-lazy class on noscript tag) or using the lazy_load() function (or one of its aliases).
Regular Youtube Video
Relaxation Ambient Music presents prefect Space Ambient Music. It was made for dreamers, also for persons which like to meditate, to imagine deep space with its nebulas and exoplanets. Fly between galaxies, nebulas and planets with our relaxing ambient space music. It specially created for stargazing, Space exploring, learning astronomy, Dreaming, Soul Healing, Stress Relief and complete relaxation. This music video will help you relax your mind, stop thinking and have a rest. 🎵 Music: Space Pilgrim Album: -- soon -- 💎 Animation: by Blue Wave Studio ⓒ Copyrights: Blue Wave Studio
Lazy-Loaded Youtube Video
This video was lazy-loaded.
Times Square, New York City, through an open window soundscape in binaural audio, captured from sunset to sunrise on the 30th floor. This video was filmed in Manhattan, showcasing the vibrant Times Square for study, work, and entertainment. The audio is authentic, not looped, and recorded on-site in real-time. Crafting this video required significant effort, but I'm excited about creating more in the future. The recording captures a blend of sirens, construction, people, traffic sounds, and more. Your support is appreciated. Enjoy! :) Patreon - https://www.patreon.com/nomadicambience Video LUTS - https://www.patreon.com/nomadicambience/shop For Ambience Sounds and Music - https://share.epidemicsound.com/lfkdnw Social Media Instagram - https://www.instagram.com/nomadicambience/ Tiktok - @nomadicambience Places You Can Find Me Spotify Apple Music Playlists Rain Walks - https://bit.ly/3p5FRJx Sounds for Sleep - http://bit.ly/3kjioqD Sounds New York - http://bit.ly/3iEFYgQ Sounds of Iceland - http://bit.ly/35LFR7R Sounds of Japan - https://bit.ly/2TZ7sOj Sounds of Norway - http://bit.ly/3kiprQc Cafe Sounds - http://bit.ly/2JW8tCq Nature Sounds - https://bit.ly/3l5SVMy City Sounds - https://bit.ly/2I3I47U Ocean Waves Sounds - http://bit.ly/2ygmPaj Rain and Thunderstorms - https://bit.ly/353w6DV Everything in the video is filmed and recorded on location. Do not copy, reproduce, or distribute any of the content. #newyork #newyorksounds #newyorkambience
Youtube Video w/o JS API
Available Youtube Data
{
"kind": "youtube#video",
"etag": "K9i_m4q__Po9Bme4X3hha5ya-2M",
"id": "xNN7iTA57jM",
"snippet": {
"publishedAt": "2017-04-06T03:23:10Z",
"channelId": "UCvVWCrxq_aZr7fN_KpaGGTA",
"title": "Forest Sounds | Woodland Ambience, Bird Song",
"description": "Bordering the old village of Mirningshire lies Mirning Woods. The locals are often here foraging for wild foods. Fresh berries, magic shrooms and fungi blooms are abundant in this area.\n-------\nSoftware used:\nE-on Vue\nPhotoshop\nAfter Effects\nAbleton\nAudition\n-------\nOne of the best sound therapy methods can be found through nature. Whether you're beginning a meditation practice or going through your daily activities, nature sounds can help keep your mind in a balanced state for improved focus throughout the day.\n-------\nApple Music \u25ba https:\/\/music.apple.com\/au\/artist\/the-guild-of-ambience\/1512893916\nSpotify \u25ba https:\/\/open.spotify.com\/artist\/2qBXko5d06O1vSmk6ujwYy\nBandcamp \u25ba https:\/\/theguildofambience.bandcamp.com\/\nGumroad \u25ba https:\/\/guildofambience.gumroad.com\/\nPatreon \u25ba https:\/\/www.patreon.com\/guildofambience\n-------\n\u00a9 2016 The Guild of Ambience\n\u2117 2016 The Guild of Ambience\n------\n#forestsounds #meditation #relaxation #naturesounds",
"thumbnails": {
"default": {
"url": "https:\/\/i.ytimg.com\/vi\/xNN7iTA57jM\/default.jpg",
"width": 120,
"height": 90
},
"medium": {
"url": "https:\/\/i.ytimg.com\/vi\/xNN7iTA57jM\/mqdefault.jpg",
"width": 320,
"height": 180
},
"high": {
"url": "https:\/\/i.ytimg.com\/vi\/xNN7iTA57jM\/hqdefault.jpg",
"width": 480,
"height": 360
},
"standard": {
"url": "https:\/\/i.ytimg.com\/vi\/xNN7iTA57jM\/sddefault.jpg",
"width": 640,
"height": 480
},
"maxres": {
"url": "https:\/\/i.ytimg.com\/vi\/xNN7iTA57jM\/maxresdefault.jpg",
"width": 1280,
"height": 720
}
},
"channelTitle": "The Guild of Ambience",
"tags": [
"woodland sounds",
"forest sounds",
"wind through trees",
"wind in trees",
"village sounds",
"village ambience",
"bird sounds",
"nature sounds",
"asmr forest",
"relaxing sounds",
"forest ambience",
"dnd sounds",
"background sounds",
"sounds for study",
"sounds for sleep",
"guild of ambience"
],
"categoryId": "1",
"liveBroadcastContent": "none",
"defaultLanguage": "en",
"localized": {
"title": "Forest Sounds | Woodland Ambience, Bird Song",
"description": "Bordering the old village of Mirningshire lies Mirning Woods. The locals are often here foraging for wild foods. Fresh berries, magic shrooms and fungi blooms are abundant in this area.\n-------\nSoftware used:\nE-on Vue\nPhotoshop\nAfter Effects\nAbleton\nAudition\n-------\nOne of the best sound therapy methods can be found through nature. Whether you're beginning a meditation practice or going through your daily activities, nature sounds can help keep your mind in a balanced state for improved focus throughout the day.\n-------\nApple Music \u25ba https:\/\/music.apple.com\/au\/artist\/the-guild-of-ambience\/1512893916\nSpotify \u25ba https:\/\/open.spotify.com\/artist\/2qBXko5d06O1vSmk6ujwYy\nBandcamp \u25ba https:\/\/theguildofambience.bandcamp.com\/\nGumroad \u25ba https:\/\/guildofambience.gumroad.com\/\nPatreon \u25ba https:\/\/www.patreon.com\/guildofambience\n-------\n\u00a9 2016 The Guild of Ambience\n\u2117 2016 The Guild of Ambience\n------\n#forestsounds #meditation #relaxation #naturesounds"
}
},
"contentDetails": {
"duration": "PT3H",
"dimension": "2d",
"definition": "hd",
"caption": "false",
"licensedContent": true,
"contentRating": {},
"projection": "rectangular"
},
"statistics": {
"viewCount": "31872956",
"likeCount": "294433",
"favoriteCount": "0",
"commentCount": "6041"
}
}Vimeo
See nebulaVimeoTracking() for available Nebula data for Vimeo videos.
Note: Nebula tracking prefers the Vimeo ID to be entered as a data attribute data-vimeo-id to match the Vimeo video ID (which will be a number). It also accepts this as the iframe ID and ultimately modifies the ID itself. If needing to select the iframe with CSS, you'll need to escape the ID selector.
Note: the query parameters api and player_id are no longer needed. In fact, they will prevent video tracking from working, so they must be removed!
Note: iframes can be lazy loaded with either hard-coded HTML (nebula-lazy class on noscript tag) or using the lazy_load() function (or one of its aliases).
Produced by: Gabe Langlois, Tanner McCarty, Jake Blauvelt
Directed and Edited by: Gabe Langlois
Principal Cinematography: Gabe Langlois, Paul Watt, Brandon Kelly
Aerial Cinematography: Gabe Langlois
Camera Assistant / Production Assistant: Christian Bertrand
Colour: David Tomiak /Silver Lining Post
Sound Mix: Keith White / Keith White Audio
Graphic Design: Javas Lehn
Featuring: jake Blauvelt, Shayne Pospisil, Jake Welch
A very special thanks to Tanner McCarty - Ride Snowboards, Andrew Goggins - Ten Barrel Brewing, Mike Last - Sigma Canada
A special thanks:
Leah Langlois
Kristen Blauvelt
The Langlois family
The Blauvelt family
Shin Campos
Stuart Andrews
Abby Andrew
Paul Watt
Christian Bertrand
Cholo Burns
Jenna Burns-Low
Adidas Snowboarding
Smith Optics
The North Face
Purl Wax
Salt and Stone
Rube and Sam Goldburg
Brandon Kelly
TBird
Dave Seaton
Lorne Lapham
Cole Brash
Shayne Pospisil
Jake Welch
Leanne Pelosi
Robin Van Gyn
Austin Sweetin
Skye Sheeley
WCP
TL City Locals
The Mighty Selkirks
This video was lazy-loaded.
Animation by Drew Tyndell
Music by Shannon Ferguson
Sound Production by Mooj Zadie
Special Thanks to Kevin Ferguson
California Inspires Me is a collaboration between Google Play and California Sunday Magazine.
Available Vimeo Data
{
"id": 132454664,
"title": "California Inspires Me: Reggie Watts",
"description": "Animation by Drew Tyndell<br \/>\r\nMusic by Shannon Ferguson<br \/>\r\nSound Production by Mooj Zadie<br \/>\r\nSpecial Thanks to Kevin Ferguson<br \/>\r\n<br \/>\r\nCalifornia Inspires Me is a collaboration between Google Play and California Sunday Magazine.",
"url": "https:\/\/vimeo.com\/132454664",
"upload_date": "2015-07-02 12:46:22",
"thumbnail_small": "https:\/\/i.vimeocdn.com\/video\/525124557-b80ce9983768edc012c970c11750c09a2bd9b629c28180c4569eaa2b94558d9e-d_100x75?region=us",
"thumbnail_medium": "https:\/\/i.vimeocdn.com\/video\/525124557-b80ce9983768edc012c970c11750c09a2bd9b629c28180c4569eaa2b94558d9e-d_200x150?region=us",
"thumbnail_large": "https:\/\/i.vimeocdn.com\/video\/525124557-b80ce9983768edc012c970c11750c09a2bd9b629c28180c4569eaa2b94558d9e-d_640?region=us",
"user_id": 2624480,
"user_name": "Drew Tyndell",
"user_url": "https:\/\/vimeo.com\/drewtyndell",
"user_portrait_small": "https:\/\/i.vimeocdn.com\/portrait\/20098251_30x30?sig=81e88db8cd96eef4fee1c450aa8d7a56c3e4d414cc3d6d8c1dead98bad462d89&v=1®ion=us",
"user_portrait_medium": "https:\/\/i.vimeocdn.com\/portrait\/20098251_75x75?sig=81e88db8cd96eef4fee1c450aa8d7a56c3e4d414cc3d6d8c1dead98bad462d89&v=1®ion=us",
"user_portrait_large": "https:\/\/i.vimeocdn.com\/portrait\/20098251_100x100?sig=81e88db8cd96eef4fee1c450aa8d7a56c3e4d414cc3d6d8c1dead98bad462d89&v=1®ion=us",
"user_portrait_huge": "https:\/\/i.vimeocdn.com\/portrait\/20098251_300x300?sig=81e88db8cd96eef4fee1c450aa8d7a56c3e4d414cc3d6d8c1dead98bad462d89&v=1®ion=us",
"stats_number_of_likes": 3903,
"stats_number_of_plays": 108216,
"stats_number_of_comments": 41,
"duration": 225,
"width": 1920,
"height": 1080,
"tags": "Computer Team, Drew Tyndell, Kevin Ferguson, Mooj Zadie, Shannon Ferguson, Google Play, Reggie Watts, California Sunday Magazine",
"embed_privacy": "anywhere"
}HTML5
video_meta() is not used with HTML5 videos, but for demo purposes, Google Analytics tracking, and MediaSession API it is shown here for reference. See nebulaHTML5VideoTracking() for available Nebula data for HTML5 videos.
iOS requires videos to be muted for autoplay to work. Nebula will not send events to Google Analytics for videos that have both autoplay and loop attributes.
This video was lazy-loaded.
Additional Notes
This function returns an array that includes data such as “raw”, “title”, “safetitle”, “description”, “thumbnail”, “author”, “date”, “url”, “duration” (which is an array of “time” and “seconds”).
This function includes two aliases: vimeo_meta() and youtube_meta().
Sidenote: Remember that Youtube and Vimeo have their own APIs for JavaScript integration. It is recommended to read through these as there are many intricate nuances in each.
Shortcode example:
Source File
Located in /libs/Functions.php on line 1468.
1 Hook
Find these filters and actions in the source code below to hook into them. Use do_action() and add_filter() in your functions file or plugin.
Filters
"pre_video_meta"Need a new filter hook? Request one here.
Actions
This function has no action hooks available. Request one? public function video_meta($provider, $id){
$override = apply_filters('pre_video_meta', null, $provider, $id);
if ( isset($override) ){return $override;}
$timer_name = $this->timer('Video Meta (' . $id . ')', 'start', '[Nebula] Videos');
//Ensure these default keys are always available
$video_metadata = array(
'origin' => $this->url_components('basedomain'),
'id' => $id,
'error' => false,
'title' => 'unknown_title',
'safetitle' => 'unknown_title'
);
if ( !empty($provider) ){
$provider = strtolower($provider);
} else {
$video_metadata['error'] = 'Video provider is required.';
$this->timer($timer_name, 'end');
return $video_metadata;
}
//Get Transients
$video_json = nebula()->transient('nebula_' . $provider . '_' . $id, function($data){
if ( $data['provider'] === 'youtube' ){
if ( !$this->get_option('google_server_api_key') && $this->is_staff() ){
trigger_error('No Google Youtube Iframe API key. Youtube videos may not be tracked!', E_USER_WARNING);
echo '<script>console.warn("No Google Youtube Iframe API key. Youtube videos may not be tracked!");</script>';
$video_metadata['error'] = 'No Google Youtube Iframe API key.';
}
$response = $this->remote_get('https://www.googleapis.com/youtube/v3/videos?id=' . $data['id'] . '&part=snippet,contentDetails,statistics&key=' . $this->get_option('google_server_api_key', ''));
if ( is_wp_error($response) ){
trigger_error('Youtube video is unavailable.', E_USER_WARNING);
$video_metadata['error'] = 'Youtube video is unavailable.';
$this->timer($data['timer_name'], 'end');
return $video_metadata;
}
$video_json = $response['body'];
} elseif ( $data['provider'] === 'vimeo' ){
$response = $this->remote_get('http://vimeo.com/api/v2/video/' . $data['id'] . '.json');
if ( is_wp_error($response) ){
trigger_error('Vimeo video is unavailable.', E_USER_WARNING);
$video_metadata['error'] = 'Vimeo video is unavailable.';
$this->timer($data['timer_name'], 'end');
return $video_metadata;
}
$video_json = $response['body'];
}
return $video_json;
}, array('provider' => $provider, 'id' => $id, 'timer_name' => $timer_name), HOUR_IN_SECONDS*12);
if ( !is_array($video_json) ){ //If it is not already an array, decode it from the JSON string
$video_json = json_decode($video_json);
}
//Check for errors
if ( empty($video_json) ){
if ( current_user_can('manage_options') || $this->is_dev() ){
if ( $provider === 'youtube' ){
$video_metadata['error'] = 'A Youtube Data API error occurred. Make sure the Youtube Data API is enabled in the Google Developer Console and the server key is saved in Nebula Options.';
} else {
$video_metadata['error'] = 'A Vimeo API error occurred (A video with ID ' . $id . ' may not exist). Tracking will not be possible.';
}
}
$this->timer($timer_name, 'end');
return $video_metadata;
} elseif ( $provider === 'youtube' && !empty($video_json->error) ){
if ( current_user_can('manage_options') || $this->is_dev() ){
$video_metadata['error'] = 'Youtube API Error: ' . $video_json->error->message;
}
$this->timer($timer_name, 'end');
return $video_metadata;
} elseif ( $provider === 'youtube' && empty($video_json->items) ){
if ( current_user_can('manage_options') || $this->is_dev() ){
$video_metadata['error'] = 'A Youtube video with ID ' . $id . ' does not exist.';
}
$this->timer($timer_name, 'end');
return $video_metadata;
} elseif ( $provider === 'vimeo' && is_array($video_json) && empty($video_json[0]) ){
$video_metadata['error'] = 'A Vimeo video with ID ' . $id . ' does not exist.';
}
//Build Data
if ( $provider === 'youtube' ){
$video_metadata['raw'] = $video_json->items[0];
$video_metadata['title'] = $video_json->items[0]->snippet->title;
$video_metadata['safetitle'] = preg_replace('/(\W)/i', '', $video_json->items[0]->snippet->title);
$video_metadata['description'] = $video_json->items[0]->snippet->description;
$video_metadata['thumbnail'] = $video_json->items[0]->snippet->thumbnails->high->url;
$video_metadata['author'] = $video_json->items[0]->snippet->channelTitle;
$video_metadata['date'] = $video_json->items[0]->snippet->publishedAt;
$video_metadata['url'] = 'https://www.youtube.com/watch?v=' . $id;
$start = new DateTime('@0'); //Unix epoch
$start->add(new DateInterval($video_json->items[0]->contentDetails->duration));
$duration_seconds = intval($start->format('H'))*60*60 + intval($start->format('i'))*60 + intval($start->format('s'));
} elseif ( $provider === 'vimeo' ){
$video_metadata['raw'] = $video_json[0];
$video_metadata['title'] = $video_json[0]->title;
$video_metadata['safetitle'] = preg_replace('/(\W)/i', '', $video_json[0]->title);
$video_metadata['description'] = $video_json[0]->description;
$video_metadata['thumbnail'] = $video_json[0]->thumbnail_large;
$video_metadata['author'] = $video_json[0]->user_name;
$video_metadata['date'] = $video_json[0]->upload_date;
$video_metadata['url'] = $video_json[0]->url;
$duration_seconds = strval($video_json[0]->duration);
}
$video_metadata['duration'] = array(
'time' => intval(gmdate("i", $duration_seconds)) . gmdate(":s", $duration_seconds),
'seconds' => $duration_seconds
);
$this->timer($timer_name, 'end');
return $video_metadata;
}
Override
To override this PHP function, use this hook in your child theme or plugin ("my_custom" can be changed):
add_filter('pre_video_meta', 'my_custom_video_meta', 10, 3); //The last integer must be 1 more than the actual parameters
function my_custom_video_meta($null, $provider, $id){ //$null is required, but can be ignored
//Write your own code here
return true; //Return true to prevent the original function from running afterwords
}
You can completely disable this PHP function with a single line actions:
add_filter('pre_video_meta', '__return_false');

