The YouTubeVideoUploadService
lets you upload videos directly to YouTube through the Google Ads API. These
videos can then be used as assets in various ad types, such as
Performance Max campaigns or
Demand Gen campaigns.
This service streamlines the workflow of creating video ads by handling the YouTube upload process, ensuring that the videos are correctly associated with your account.
Key concepts
Before you begin, it's important to understand how video uploads are managed and the different states they can go through.
Channel ownership
When you upload a video, you can specify the destination YouTube channel using
the channel_id field in the YouTubeVideoUpload
resource:
- Advertiser-owned (brand) channel: Provide the
channel_idof a YouTube channel owned by the advertiser. Uploading to a brand channel allows for more control over the video's privacy and visibility. - Google-managed channel: If
channel_idis omitted, the video is uploaded to a Google-managed YouTube channel associated with the Google Ads account.
Upload states
The lifecycle of a YouTube video upload is tracked by the state field.
The YouTubeVideoUploadState
enum defines the following states:
| State | Description |
|---|---|
PENDING |
The video is being uploaded. |
UPLOADED |
The video has been successfully uploaded and is being processed by YouTube. |
PROCESSED |
The video has been successfully processed and is ready for use. |
FAILED |
The upload or processing failed and cannot be completed. |
REJECTED |
The video was rejected due to validation or policy reasons. |
UNAVAILABLE |
The video state is unavailable; it may have been removed from YouTube. |
Privacy settings
The video_privacy field controls who can see the uploaded video. The
YouTubeVideoPrivacy
enum supports:
PUBLIC: The video is available to anyone on YouTube. (Only allowed for brand channels).UNLISTED: The video is not searchable but can be viewed by anyone with the link. This is the default and the only option for Google-managed channels.
Upload a video
To upload a video, you must use a multi-part request to the
CreateYouTubeVideoUpload method. The request contains both the metadata for
the upload and the video file itself.
1. Initiate the upload
Construct a CreateYouTubeVideoUploadRequest
specifying the:
customer_id: Your Google Ads customer ID.you_tube_video_upload: AYouTubeVideoUploadobject with thevideo_title,video_description, and optionally thechannel_idandvideo_privacy.
If you are using a client library, call the
CreateYouTubeVideoUpload
method, passing your video file, and the video upload will be handled
internally.
Java
This example is not yet available in Java; you can take a look at the other languages.
C#
This example is not yet available in C#; you can take a look at the other languages.
PHP
This example is not yet available in PHP; you can take a look at the other languages.
Python
yt_service: YouTubeVideoUploadServiceClient = client.get_service( "YouTubeVideoUploadService" ) create_upload_request: CreateYouTubeVideoUploadRequest = ( youtube_video_upload_service.CreateYouTubeVideoUploadRequest() ) create_upload_request.customer_id = customer_id create_upload_request.you_tube_video_upload.video_title = "Test Video" create_upload_request.you_tube_video_upload.video_description = ( "Test Video Description" ) create_upload_request.you_tube_video_upload.video_privacy = ( client.enums.YouTubeVideoPrivacyEnum.UNLISTED ) video_upload_resource_name: str with open(video_file_path, "rb") as stream: response: CreateYouTubeVideoUploadResponse = ( yt_service.create_you_tube_video_upload( stream=stream, request=create_upload_request, retry=None, ) ) print(f"Created YouTube video upload: {response.resource_name}")
Ruby
This example is not yet available in Ruby; you can take a look at the other languages.
Perl
This example is not yet available in Perl; you can take a look at the other languages.
curl
# # Use the --i curl parameter to capture response headers in the $RESPONSE # variable. FILE_SIZE=$(wc -c < "${VIDEO_FILE_NAME}" | tr -d '\r') RESPONSE=$(curl -i -f -v -s --request POST \ "https://googleads.googleapis.com/resumable/upload/v${API_VERSION}/customers/${CUSTOMER_ID}:youTubeVideoUploads:create" \ --header "Content-Type: application/json" \ --header "developer-token: ${DEVELOPER_TOKEN}" \ --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ --header "X-Goog-Upload-Protocol: resumable" \ --header "X-Goog-Upload-Command: start" \ --header "X-Goog-Upload-Header-Content-Length: ${FILE_SIZE}" \ --data @- <<EOF { "customer_id": "${CUSTOMER_ID}", "you_tube_video_upload": { "video_title": "${VIDEO_TITLE}", "video_description": "${VIDEO_DESCRIPTION}", "video_privacy": "UNLISTED" } } EOF ) # Extract the value of the "x-goog-upload-url" header from the HTTP response. UPLOAD_URL=$(echo "${RESPONSE}" \ | grep -i '^x-goog-upload-url' \ | awk '{print $2}' \ | tr -d '\r') CHUNK_SIZE=$(echo "${RESPONSE}" \ | grep -i '^x-goog-upload-chunk-granularity' \ | awk '{print $2}' \ | tr -d '\r')
If you are using REST, the following section describes how to manage the video upload.
2. Upload the video
When you send a REST request to the
CreateYouTubeVideoUpload
method, the response contains the URL to be used for uploading the video bytes
in the x-goog-upload-url HTTP response header, along with other metadata such
as the expected size of each chunk for chunked uploads.
You can also declare the size of the video you are going to upload initially,
when starting the process, with the x-goog-upload-header-content-length
HTTP request header.
For a full description of the HTTP headers used in the video upload protocol, refer to the following code example:
# Take the first ${CHUNK_SIZE} bytes of the video file and upload them. head -c ${CHUNK_SIZE} ${VIDEO_FILE_NAME} | curl -i -v -X PUT "${UPLOAD_URL}" \ --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ --header "X-Goog-Upload-Offset: 0" \ --header "X-Goog-Upload-Command: upload" \ --header "Content-Length: ${CHUNK_SIZE}" \ --data-binary @- # Query the status of the upload. QUERY_RESPONSE=$(curl -i -s -X POST "${UPLOAD_URL}" \ --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ --header "X-Goog-Upload-Command: query") # Extract the value of the "x-goog-upload-size-received" header from the HTTP # response. UPLOADED_BYTES=$(echo "${QUERY_RESPONSE}" \ | grep -i '^x-goog-upload-size-received' \ | awk '{print $2}' \ | tr -d '\r') echo "Uploaded ${UPLOADED_BYTES} bytes." REMAINING_BYTES=$((FILE_SIZE - UPLOADED_BYTES)) echo "${REMAINING_BYTES} bytes remaining to upload." FINALIZE_RESPONSE=$(tail -c ${REMAINING_BYTES} ${VIDEO_FILE_NAME} | curl -v -X PUT "${UPLOAD_URL}" \ --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ --header "X-Goog-Upload-Offset: ${UPLOADED_BYTES}" \ --header "X-Goog-Upload-Command: upload, finalize" \ --data-binary @-) UPLOADED_VIDEO_RESOURCE_NAME=$(echo $FINALIZE_RESPONSE | jq -r '.resourceName')
3. Retrieve the video upload state
After you started a video upload, you can retrieve its state by querying the
you_tube_video_upload resource with GAQL:
Java
This example is not yet available in Java; you can take a look at the other languages.
C#
This example is not yet available in C#; you can take a look at the other languages.
PHP
This example is not yet available in PHP; you can take a look at the other languages.
Python
# Retrieve the metadata of the newly uploaded video. query: str = f""" SELECT you_tube_video_upload.resource_name, you_tube_video_upload.video_id, you_tube_video_upload.state FROM you_tube_video_upload WHERE you_tube_video_upload.resource_name = '{video_upload_resource_name}'""" ga_service: GoogleAdsServiceClient = client.get_service("GoogleAdsService") stream: Iterator[SearchGoogleAdsStreamResponse] = ga_service.search_stream( customer_id=customer_id, query=query ) for row in itertools.chain.from_iterable(batch.results for batch in stream): video = row.you_tube_video_upload print( f"Video with ID {row.you_tube_video_upload.video_id} was found in state {row.you_tube_video_upload.state}." )
Ruby
This example is not yet available in Ruby; you can take a look at the other languages.
Perl
This example is not yet available in Perl; you can take a look at the other languages.
curl
curl -i -v -X POST \ "https://qa-prod-googleads.sandbox.googleapis.com/v${API_VERSION}/customers/${CUSTOMER_ID}/googleAds:search" \ --header "Content-Type: application/json" \ --header "Developer-Token: ${DEVELOPER_TOKEN}" \ --header "login-customer-id: ${MANAGER_CUSTOMER_ID}" \ --header "Authorization: Bearer ${OAUTH2_ACCESS_TOKEN}" \ --data @- <<EOF { "query": "SELECT you_tube_video_upload.resource_name, you_tube_video_upload.video_id, you_tube_video_upload.state FROM you_tube_video_upload WHERE you_tube_video_upload.resource_name = '$UPLOADED_VIDEO_RESOURCE_NAME'" } EOF
Manage uploads
After a video upload is completed, you can use it as a video asset.
Use the uploaded video
After a video reaches the PROCESSED state, you can find its YouTube video ID
in the video_id field of the YouTubeVideoUpload resource.
Use this video_id to create a VideoAsset or
link it directly to ad types that support YouTube videos by referencing the
video ID.
Update metadata
You can update the metadata of a video uploaded through this API using the
UpdateYouTubeVideoUpload method. Only the video_title, video_description,
and video_privacy fields can be updated.
Remove uploads
If you need to delete videos uploaded with the Google Ads API, use the
RemoveYouTubeVideoUpload method. This will remove the video from both the
Google Ads asset library and YouTube.