Handler: tap.youtube_reporting
Pull YouTube Reporting API bulk reports and land them in external_metrics, through the same external_metrics_writer every other metrics tap uses. The seeded row, youtube_reach, reads the reach report: thumbnail impressions and thumbnail click-through rate per video per day. A thumbnail exists to move exactly that number, and before this tap no YouTube number reached the database at all.
How the Reporting API delivers data
From Google’s bulk reports guide:- A reporting job is created once per report type. The handler creates it on its first run and caches the id in the row’s
state. - YouTube writes one CSV per Pacific-time day. The first arrives within 48 hours of the job’s creation, along with reports for the 30 days before the job existed.
- Reports stay downloadable for 60 days (30 for the historical ones).
- A corrected day arrives as a NEW report with a new id. The writer’s natural-key upsert makes it overwrite the earlier value.
Row configuration
config:
post_id: the post whosemedia_assetsrow holds that YouTube id.medium:longfor avideoasset,shortforvideo_short, orunknown.
video_id in dimension_fields. With post_id as the post field the writer leaves slug NULL, so dimensions is the only per-video part of the natural key.
One-time setup
Two operator steps:-
Grant the analytics scope. Scopes live in the token, not in code:
This keeps every scope the stored token already holds;
--reset-scopesnarrows on purpose. Check the result withpoindexter integrations youtube scopes. - Enable the YouTube Reporting API for the OAuth client’s Google Cloud project: APIs & Services → Library → “YouTube Reporting API”. It is a separate API from the YouTube Data API the uploads use.
jobs/run_taps.py) walks every enabled tap
hourly and does not honour a row’s schedule yet, so this row runs hourly.
Each run lands only reports it has not seen, so the extra runs are cheap, and a
failing run raises a finding at most once per findings.tap_failure.cooldown_minutes.
Failure posture
- YouTube publishing not set up (
plugin.publish_adapter.youtube.enabledfalse or the OAuth secrets missing): a quiet 0-record run. Most installs never publish to YouTube, so that zero is legitimate. - Missing scope or disabled API: the run raises with the fix above. The tap runner records it on the row (
poindexter taps show youtube_reach) and raises atap_failurefinding, routed fromtap_failure_alert_after_consecutivefailures on. - Anything else (5xx, network): raises and retries on the next run. Landed reports are remembered one at a time, so a run that dies half-way resumes where it stopped.
Reading it
video_thumbnail_impressions_ctr is a fraction or a percentage. The handler stores the value exactly as delivered. Compare the first reports with YouTube Studio’s Reach tab before building thresholds on it.