E-commerce · Performance Max video
How to add product and UGC videos to Performance Max: from clip to asset group
Performance Max does not take video files: every video asset is a YouTube video referenced by its ID, so the path is clip, checked MP4, upload to the brand's own YouTube channel, then a link to the asset group. We keep clips at 11 seconds or longer, deliver 16:9, 1:1 and 9:16 versions, attach a handful rather than dozens, and verify each step by reading the result back. Most of what went wrong for us came from steps that reported success without doing the work.
Updated
What it takes to put a video into Performance Max
To put a video into a Google Ads Performance Max campaign, you upload it to YouTube and link that YouTube video to an asset group; Google Ads does not host raw video files. Performance Max is the Google Ads campaign type that serves one set of assets (text, images, video) across Google's surfaces, and an asset group is its bundle of assets for one theme. A video shorter than 10 seconds is rejected at linking with the error YOUTUBE_VIDEO_TOO_SHORT, so we only consider clips of 11 seconds or more.
Our videos come from creator videos (user-generated content, or UGC) handed to the media buyer, from montages rendered from the store's own photos and live prices, and, experimentally, from clips generated out of one product photo. All follow the same path: check, format, upload, attach, verify.
Step 1: hand creator videos to the media buyer as a list, not a folder
Creator videos arrive in a shared drive, one folder per brand. The media buyer does not work from the folder: every new video becomes a row in a shared sheet with a file link, its subfolder and a status, so nothing is missed or used twice. Images are skipped.
Deduplicating creator videos needs two keys. The same content is often uploaded again under a new file ID, so a file is dropped if its ID is already in the sheet or if a file with the same normalised name (lower case, extension removed, spaces collapsed) is. The drive's creation date is not reliable for old archives: a backlog imported in one day gets that day's date on every file, so such folders are treated as legacy and skipped.
The handoff runs as a dry run first, printing the planned rows and counts, and only then writes; the sheet accepts at most 10 linked-file chips per request, so links go in chunks of 10.
Step 2: convert the clip to an MP4 every platform accepts, and check the result
Clips often arrive as WebM (VP9 video with Vorbis or Opus audio) or MOV, and merely changing the container gives a file that editors and upload forms refuse. We re-encode to H.264 video with AAC audio, set the pixel format to yuv420p (without it some phones and players show a black screen), and move the index to the start of the file with +faststart so playback starts before the download ends.
The MP4 is usually larger than the WebM, and that is not a wrong setting: VP9 compresses 30 to 50% better than H.264 at equal quality. On one measured clip, 44 MB of WebM became 64 MB of MP4 at CRF 18 (CRF is the constant-quality setting; lower means better quality). When size matters more than detail, CRF 23 gives roughly half the size.
The check after conversion matters more than the conversion. FFmpeg can exit with code 0 and still leave a truncated file, for example when the disk fills or the source is corrupt halfway through. After every conversion we read the result with ffprobe and compare its duration with the original; a difference above 0.5 seconds is reported as a failure, and in that case the original is never deleted.
Step 3: produce the three Performance Max formats and a script built for silent viewing
Performance Max video comes in landscape 16:9 (1920×1080), square 1:1 (1080×1080) and vertical 9:16 (1080×1920). We deliver all three for every concept, each at least 10 seconds and ideally around 15, as MP4. Each format is recomposed, not cropped blindly from another.
The script follows hook, body, call to action: the first 3 seconds must stop the scroll, a new shot every 2 to 3 seconds keeps momentum, and the end states the offer. Captions are written to make sense with the sound off, at most 5 to 7 words per frame, large and high contrast, kept clear of the bottom strip where the Shorts and Reels interface sits. Prices and discounts on screen come from the store's live data (old price struck through, new price, percentage off) and are never written by the model.
Rendering traps produced broken files without an error: a crop whose size changes over time gave a 0-byte file, and two formats rendered in parallel collided on temporary files and produced a 48-byte file. Formats now render one after another, and the renderer checks its output and fails loudly.
Step 4: upload to the brand's own YouTube channel, then attach in two calls
Each brand has its own YouTube channel, all Brand Accounts under one Google account and one OAuth app. Consent is given once per channel, and the refresh token can only upload to the channel chosen at consent, so we confirm the channel right after by listing it with the read-only scope. In Testing mode, refresh tokens for a sensitive scope expire after about 7 days: fine for one batch, not for a daily job.
Upload quota limits volume. One YouTube upload costs 1,600 units of a 10,000-unit daily allowance, which is about 6 uploads a day, and the allowance resets at midnight Pacific time.
Attaching a YouTube video to Performance Max is two API calls: create a YouTube video asset from the video ID, then link the asset to the asset group with field type YOUTUBE_VIDEO (not VIDEO, which is rejected as incompatible). The asset group must already have a final URL, or the link fails with FINAL_URL_REQUIRED. On a new asset group still under review, linking in a batch fails with CONCURRENT_MODIFICATION, so we link one video at a time with retries.
We attach roughly 5 to 9 videos per asset group, chosen from creatives that already performed in paid social. For a library of 363 videos, a daily job ranks them by the product's stock and recent sales, skips products with no stock, takes at most 3 per product and uploads 5 a day.
The traps we hit and how we catch them now
The wrong channel. Videos attached to one brand's asset group were hosted on a generic upload channel instead of the brand's channel. Nothing failed and the ads ran. We found it by reading the video ID of every attached asset and asking YouTube which channel hosts it. We re-uploaded, attached the new copies and removed the old links.
Removed links in counts. Queries over asset-group assets also return removed links, so videos looked doubled. Filter on ENABLED.
Videos deleted from YouTube. In one channel audit, 8 videos in our upload register no longer existed on YouTube, so ad assets pointing at them may be broken. The register (drive file ID to YouTube ID) is what we audit against.
A time cut-off that skips failures. A separate importer collected clip links shared in a group chat and fetched only links newer than the last clip that arrived. Any link that failed once was skipped for good, because later links moved the cut-off past it. After 16 days, 8 of 59 links had never arrived: 4 were never tried and 4 had failed once, and 3 of those worked on a fresh try. Each link now has its own row with a state; retries read the state, not a date, and a 10-day window, longer than the transfer service's 7-day expiry, ends retries on dead links, which are reported.
A job that ran but did nothing. After the daily upload moved to a server, it ran on schedule for two days and uploaded nothing: one script still pointed at a credentials file on a laptop, and the channel tokens were missing from the server's environment. After any deploy we now run the pipeline once for real and check the register.
Captions that repeat the speaker. A model captioning a talking-head creator video can copy the creator's spoken self-introduction into the brand's voice; we found one case in about 90 captions, and a check on the output now rejects it.
Where we were wrong
Two parts we built are not in production. The montage styles that use real demo footage from suppliers are blocked: the clips carry burned-in text in other languages, and the OCR we used to reject them was unreliable, so those styles fall back to photos. Generating a clip from one product photo is wired and tested against a hosted model but waits for billing to be enabled, and its output is about 5 seconds (81 frames at 16 frames per second, 480p). That is under the 10-second minimum, so such a clip can only be one shot inside a longer edit.
We also trusted success signals too much: the scheduler ran and the ads served while videos sat on the wrong channel or were never uploaded. We stopped chasing Google's Ad Strength label: it is a guidance score, not a performance measure, and rewriting the assets of a working campaign to raise it resets learning.
Limits and checklist
This method gets correct video into the right asset group on the right channel. It does not show that the videos sell: we have no controlled test of what video adds, and popular figures about silent viewing are industry claims, not our measurements.
Checklist. Clip of 11 seconds or more; H.264 and AAC MP4, duration checked; three formats, recomposed; captions readable on mute; prices from live data; brand's own channel, confirmed; final URL set; YOUTUBE_VIDEO, linked one at a time; count ENABLED only; hosting channel checked; one register row per file.
Questions and answers
Can I upload a video file directly to a Performance Max campaign through the Google Ads API?
No. Google Ads does not host raw video. You upload the video to YouTube first, either through the Google Ads asset library, which hosts it for you, or through the YouTube Data API, then create a YouTube video asset from the video ID and link it to the asset group with field type YOUTUBE_VIDEO. The asset group must already have a final URL, or the link is rejected.
What is the minimum length for a Performance Max video?
A video shorter than 10 seconds is rejected when you link it to an asset group, with the error YOUTUBE_VIDEO_TOO_SHORT. We keep clips at 11 seconds or longer and aim for about 15 seconds, delivering landscape 16:9, square 1:1 and vertical 9:16 versions of each concept so Google does not have to generate or crop its own.
How many videos can I upload to YouTube per day through the API?
With the default quota, one upload through the YouTube Data API costs 1,600 units of a 10,000-unit daily allowance, which allows about 6 uploads a day. The allowance resets at midnight Pacific time. Changing an existing video's privacy costs 50 units, so plan mass updates and large upload batches on different days.
Why does my converted MP4 come out larger than the original WebM?
WebM files usually contain VP9 video, which compresses 30 to 50% better than H.264 at the same quality. To make an MP4 that every editor, phone and upload form accepts, you re-encode to H.264 with AAC audio, so the file grows. If size matters more than detail, use a higher CRF value, such as 23 instead of 18, for roughly half the size.
Why do linked videos appear twice when I query a Performance Max asset group?
The query over asset-group assets also returns links that were removed. Filter on status ENABLED to count only active videos. If you try to remove a link that was already removed, the API returns an error that only confirms it is already gone, not a real failure.
How to cite this
Going Stellar (2026). How to add product and UGC videos to Performance Max: from clip to asset group. GOING STELLAR S.R.L..
https://goingstellar.ro/methods/pmax-video-assets-from-product-and-ugc-clips/