From c39b7b43725b5d23dc76830373b70dd5ae89e7aa Mon Sep 17 00:00:00 2001 From: Kang-Kyu Lee Date: Wed, 21 May 2025 13:14:56 -0700 Subject: [PATCH 1/2] Add engaged_views to playlist; remove isCurated (not supported) --- lib/yt/collections/reports.rb | 1 - lib/yt/models/playlist.rb | 5 ++++- spec/requests/as_account/playlist_spec.rb | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/yt/collections/reports.rb b/lib/yt/collections/reports.rb index 7be86ba5..41c67f93 100644 --- a/lib/yt/collections/reports.rb +++ b/lib/yt/collections/reports.rb @@ -210,7 +210,6 @@ def reports_params params[:filters] = ((params[:filters] || '').split(';') + ["country==US"]).compact.uniq.join(';') if @dimension == :state && !@state params[:filters] = ((params[:filters] || '').split(';') + ["country==#{@country}"]).compact.uniq.join(';') if @country && !@state params[:filters] = ((params[:filters] || '').split(';') + ["province==US-#{@state}"]).compact.uniq.join(';') if @state - params[:filters] = ((params[:filters] || '').split(';') + ['isCurated==1']).compact.uniq.join(';') if @dimension == :playlist params[:filters] = ((params[:filters] || '').split(';') + ['insightPlaybackLocationType==EMBEDDED']).compact.uniq.join(';') if @dimension == :embedded_player_location params[:filters] = ((params[:filters] || '').split(';') + ['insightTrafficSourceType==RELATED_VIDEO']).compact.uniq.join(';') if @dimension == :related_video params[:filters] = ((params[:filters] || '').split(';') + ['insightTrafficSourceType==YT_SEARCH']).compact.uniq.join(';') if @dimension == :search_term diff --git a/lib/yt/models/playlist.rb b/lib/yt/models/playlist.rb index d5f22953..68e545ca 100644 --- a/lib/yt/models/playlist.rb +++ b/lib/yt/models/playlist.rb @@ -160,6 +160,9 @@ def delete_playlist_items(attributes = {}) # @macro report_by_playlist_dimensions has_report :views, Integer + # @macro report_by_playlist_dimensions + has_report :engaged_views, Integer + # @macro report_by_playlist_dimensions has_report :estimated_minutes_watched, Integer @@ -202,7 +205,7 @@ def reports_params else params[:ids] = "channel==#{channel_id}" end - params[:filters] = "playlist==#{id};isCurated==1" + params[:filters] = "playlist==#{id}" end end diff --git a/spec/requests/as_account/playlist_spec.rb b/spec/requests/as_account/playlist_spec.rb index 256a2314..296977c9 100644 --- a/spec/requests/as_account/playlist_spec.rb +++ b/spec/requests/as_account/playlist_spec.rb @@ -178,11 +178,12 @@ let(:id) { test_account.channel.playlists.first.id } before do - allow(Date).to receive(:today).and_return(Date.new(2020, 2, 5)) + allow(Date).to receive(:today).and_return(Date.new(2025, 5, 20)) end it 'returns valid reports for playlist-related metrics' do expect{playlist.views}.not_to raise_error + expect{playlist.engaged_views}.not_to raise_error expect{playlist.playlist_starts}.not_to raise_error expect{playlist.average_time_in_playlist}.not_to raise_error expect{playlist.views_per_playlist_start}.not_to raise_error From 10ccbe176b635322eb65aa2dec0bf48b789dae12 Mon Sep 17 00:00:00 2001 From: Kang-Kyu Lee Date: Wed, 21 May 2025 13:52:46 -0700 Subject: [PATCH 2/2] Add engaged_views to video groups --- lib/yt/models/video_group.rb | 3 +++ .../as_content_owner/content_owner_spec.rb | 5 +++-- spec/support/global_hooks.rb | 14 ++++++++++++++ spec/support/vcr.rb | 13 +++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/yt/models/video_group.rb b/lib/yt/models/video_group.rb index 43ab8e83..d725c834 100644 --- a/lib/yt/models/video_group.rb +++ b/lib/yt/models/video_group.rb @@ -37,6 +37,9 @@ class VideoGroup < Base # @macro report_by_video_dimensions has_report :views, Integer + # @macro report_by_video_dimensions + has_report :engaged_views, Integer + # @macro report_by_video_dimensions has_report :estimated_minutes_watched, Integer diff --git a/spec/requests/as_content_owner/content_owner_spec.rb b/spec/requests/as_content_owner/content_owner_spec.rb index 7a550a03..14ca9ab8 100644 --- a/spec/requests/as_content_owner/content_owner_spec.rb +++ b/spec/requests/as_content_owner/content_owner_spec.rb @@ -2,7 +2,7 @@ require 'yt/models/content_owner' require 'yt/models/match_policy' -describe Yt::ContentOwner, :partner do +describe Yt::ContentOwner, :partner, :vcr do describe '.partnered_channels' do let(:partnered_channels) { $content_owner.partnered_channels } @@ -66,7 +66,7 @@ end describe '.video_groups' do - let(:video_group) { $content_owner.video_groups.first } + let(:video_group) { test_content_owner.video_groups.first } specify 'returns the first video-group created by the account' do expect(video_group).to be_a Yt::VideoGroup @@ -77,6 +77,7 @@ specify 'allows to run reports against each video-group' do expect(video_group.views).to be + expect(video_group.engaged_views).to be end end diff --git a/spec/support/global_hooks.rb b/spec/support/global_hooks.rb index 2b74d0e4..8b635478 100644 --- a/spec/support/global_hooks.rb +++ b/spec/support/global_hooks.rb @@ -5,6 +5,15 @@ module Helpers def test_account @test_account ||= Yt::Account.new(refresh_token: ENV['YT_TEST_REFRESH_TOKEN']) end + + # Create one Youtube Partner channel, authenticated as the content owner + def test_content_owner + @test_content_owner ||= begin + attrs = { refresh_token: ENV['YT_TEST_CONTENT_OWNER_REFRESH_TOKEN'] } + attrs[:owner_name] = ENV['YT_TEST_CONTENT_OWNER_NAME'] + Yt::ContentOwner.new attrs + end + end end RSpec.configure do |config| @@ -23,4 +32,9 @@ def test_account config.before :each, server_app: true do allow(Yt.configuration).to receive(:api_key).and_return(ENV['YT_TEST_API_KEY']) end + + config.before :each, partner: true do + allow(Yt.configuration).to receive(:client_id).and_return(ENV['YT_TEST_PARTNER_CLIENT_ID']) + allow(Yt.configuration).to receive(:client_secret).and_return(ENV['YT_TEST_PARTNER_CLIENT_SECRET']) + end end diff --git a/spec/support/vcr.rb b/spec/support/vcr.rb index 45c10a5e..88f4b8b8 100644 --- a/spec/support/vcr.rb +++ b/spec/support/vcr.rb @@ -32,4 +32,17 @@ c.filter_sensitive_data("") do |interaction| interaction.request.headers['Authorization'].first rescue nil end + + c.filter_sensitive_data("") { ENV['YT_TEST_CONTENT_OWNER_NAME'] } + c.filter_sensitive_data("") { ENV['YT_TEST_PARTNER_CLIENT_ID'] } + c.filter_sensitive_data("") { ENV['YT_TEST_PARTNER_CLIENT_SECRET'] } + c.filter_sensitive_data("") { CGI.escape(ENV['YT_TEST_CONTENT_OWNER_REFRESH_TOKEN']) } + c.filter_sensitive_data("") do |interaction| + begin + body = JSON.parse(interaction.response.body) + body['access_token'] + rescue + # noop + end + end end