| layout | title | description |
|---|---|---|
default |
Analytics API |
Query YouTube Analytics data for channel statistics, demographics, and revenue. |
Query YouTube Analytics data for your channel:
Reports: Flexible analytics queries
- Custom date ranges
- Multiple metrics and dimensions
- Filtering and sorting
- Pagination support
Convenience Methods: Common queries
- Channel overview statistics
- Daily view breakdown
- Top videos by views
- Geographic and device breakdown
- Revenue reports (if monetized)
Report Processing: Easy data access
- Typed accessors for row data
- Aggregate totals
- Column header metadata
Create a new Analytics API client.
client := analytics.NewClient(
analytics.WithAccessToken("your-access-token"),
)Integrate with AuthClient for automatic token refresh.
client := analytics.NewClient(
analytics.WithTokenProvider(authClient.AccessToken),
)client := analytics.NewClient(
analytics.WithHTTPClient(customHTTPClient),
analytics.WithAccessToken("static-token"),
analytics.WithTokenProvider(tokenFunc),
)Execute a custom analytics query.
report, err := client.Query(ctx, &analytics.QueryParams{
IDs: "channel==MINE",
StartDate: "2025-01-01",
EndDate: "2025-01-31",
Metrics: "views,estimatedMinutesWatched,averageViewDuration",
Dimensions: "day",
Sort: "day",
})
if err != nil {
log.Fatal(err)
}| Parameter | Required | Description |
|---|---|---|
IDs |
Yes | Channel or content owner (channel==MINE or channel==UC1234) |
StartDate |
Yes | Start date in YYYY-MM-DD format |
EndDate |
Yes | End date in YYYY-MM-DD format |
Metrics |
Yes | Comma-separated metrics to retrieve |
Dimensions |
No | Comma-separated dimensions to group by |
Filters |
No | Semicolon-separated dimension filters |
Sort |
No | Comma-separated sort fields (prefix - for descending) |
MaxResults |
No | Maximum number of rows to return |
StartIndex |
No | 1-based index of first row |
Currency |
No | Currency code for revenue metrics (USD, EUR, etc.) |
Filter results by dimension values.
report, err := client.Query(ctx, &analytics.QueryParams{
IDs: "channel==MINE",
StartDate: "2025-01-01",
EndDate: "2025-01-31",
Metrics: "views,estimatedMinutesWatched",
Filters: "video==dQw4w9WgXcQ;country==US",
})Get overall channel statistics.
report, err := client.QueryChannelViews(ctx, "2025-01-01", "2025-01-31")
// Returns: views, estimatedMinutesWatched, averageViewDuration,
// subscribersGained, subscribersLostGet daily breakdown of views.
report, err := client.QueryDailyViews(ctx, "2025-01-01", "2025-01-31")
// Returns: day, views, estimatedMinutesWatchedGet top videos by view count.
report, err := client.QueryTopVideos(ctx, "2025-01-01", "2025-01-31", 10)
// Returns: video, views, estimatedMinutesWatched, likes, commentsGet views by country.
report, err := client.QueryCountryBreakdown(ctx, "2025-01-01", "2025-01-31")
// Returns: country, views, estimatedMinutesWatchedGet views by device type.
report, err := client.QueryDeviceBreakdown(ctx, "2025-01-01", "2025-01-31")
// Returns: deviceType, views, estimatedMinutesWatchedGet revenue metrics (requires monetization).
report, err := client.QueryRevenueReport(ctx, "2025-01-01", "2025-01-31")
// Returns: day, estimatedRevenue, estimatedAdRevenue, monetizedPlaybacks, cpmtype Report struct {
Kind string // "youtubeAnalytics#resultTable"
ColumnHeaders []ColumnHeader // Column metadata
RawRows [][]any // Raw row data
}
type ColumnHeader struct {
Name string // Column name
ColumnType string // "DIMENSION" or "METRIC"
DataType string // "STRING", "INTEGER", "FLOAT", etc.
}Use Rows() for typed access to report data.
for _, row := range report.Rows() {
day := row.GetString("day")
views := row.GetInt("views")
minutes := row.GetFloat("estimatedMinutesWatched")
fmt.Printf("%s: %d views, %.1f minutes watched\n", day, views, minutes)
}// Get string value
day := row.GetString("day")
// Get integer value (converts from float64)
views := row.GetInt("views")
// Get float value
minutes := row.GetFloat("estimatedMinutesWatched")totalViews := report.TotalViews()
totalMinutes := report.TotalMinutesWatched()
fmt.Printf("Total: %d views, %.0f minutes\n", totalViews, totalMinutes)| Metric | Description |
|---|---|
views |
Number of video views |
estimatedMinutesWatched |
Total watch time in minutes |
averageViewDuration |
Average view duration in seconds |
subscribersGained |
New subscribers |
subscribersLost |
Lost subscribers |
likes |
Number of likes |
dislikes |
Number of dislikes |
comments |
Number of comments |
shares |
Number of shares |
estimatedRevenue |
Total estimated revenue |
estimatedAdRevenue |
Ad revenue |
cpm |
Cost per thousand impressions |
monetizedPlaybacks |
Monetized playback count |
| Dimension | Description |
|---|---|
day |
Daily breakdown |
month |
Monthly breakdown |
video |
Per-video breakdown |
country |
Country code (US, GB, etc.) |
province |
Province/state |
city |
City |
deviceType |
MOBILE, DESKTOP, TV, GAME_CONSOLE, etc. |
operatingSystem |
Operating system |
ageGroup |
Age demographic |
gender |
Gender demographic |
trafficSourceType |
Traffic source |
var analyticsErr *analytics.AnalyticsError
if errors.As(err, &analyticsErr) {
fmt.Printf("Status: %d, Code: %s\n", analyticsErr.StatusCode, analyticsErr.Code)
if analyticsErr.IsPermissionDenied() {
log.Println("Need proper OAuth scope or channel access")
}
if analyticsErr.IsInvalidArgument() {
log.Println("Invalid query parameter")
}
if analyticsErr.IsQuotaExceeded() {
log.Println("Rate limit exceeded")
}
}package main
import (
"context"
"fmt"
"log"
"time"
"github.com/Its-donkey/yougopher/youtube/analytics"
"github.com/Its-donkey/yougopher/youtube/auth"
)
func main() {
ctx := context.Background()
// Setup authentication
authClient := auth.NewAuthClient(auth.Config{
ClientID: "your-client-id",
ClientSecret: "your-client-secret",
RedirectURL: "http://localhost:8080/callback",
Scopes: []string{auth.ScopeReadOnly, auth.ScopePartner},
})
// ... complete OAuth flow ...
// Create analytics client
client := analytics.NewClient(
analytics.WithTokenProvider(authClient.AccessToken),
)
// Get date range (last 30 days)
endDate := time.Now().Format("2006-01-02")
startDate := time.Now().AddDate(0, 0, -30).Format("2006-01-02")
// Channel overview
overview, err := client.QueryChannelViews(ctx, startDate, endDate)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total views: %d\n", overview.TotalViews())
fmt.Printf("Total watch time: %.0f minutes\n", overview.TotalMinutesWatched())
// Top videos
topVideos, err := client.QueryTopVideos(ctx, startDate, endDate, 5)
if err != nil {
log.Fatal(err)
}
fmt.Println("\nTop 5 Videos:")
for i, row := range topVideos.Rows() {
fmt.Printf("%d. Video %s: %d views\n", i+1, row.GetString("video"), row.GetInt("views"))
}
// Daily trend
daily, err := client.QueryDailyViews(ctx, startDate, endDate)
if err != nil {
log.Fatal(err)
}
fmt.Println("\nDaily Views:")
for _, row := range daily.Rows() {
fmt.Printf(" %s: %d views\n", row.GetString("day"), row.GetInt("views"))
}
}Client is safe for concurrent use.