El YouTubeVideoUploadService
te permite subir videos directamente a YouTube a través de la API de Google Ads. Luego, estos
videos se pueden usar para crear recursos de video en varios tipos de anuncios, como
las campañas de máximo rendimiento o
las campañas de generación de demanda.
Este servicio optimiza el flujo de trabajo de creación de anuncios de video, ya que controla el proceso de carga de YouTube y garantiza que los videos estén asociados correctamente con tu cuenta.
Conceptos clave
Antes de comenzar, es importante comprender cómo se administran las cargas de videos y los diferentes estados por los que pueden pasar.
Flujo de trabajo de extremo a extremo
Para subir un archivo de video y publicarlo en un anuncio, se requieren cuatro pasos secuenciales:
| Paso | Servicio y método | Resumen |
|---|---|---|
| 1. Inicia y sube bytes de video | CreateYouTubeVideoUpload en YouTubeVideoUploadService |
Sube los metadatos del video y el archivo binario para crear un recurso YouTubeVideoUpload (customers/{customer_id}/youTubeVideoUploads/{video_upload_id}). |
| 2. Consulta el estado de procesamiento | SearchStream en GoogleAdsService |
Consulta you_tube_video_upload hasta que state = 'PROCESSED' y se complete el video_id de YouTube de 11 caracteres. |
| 3. Crea un recurso de video reutilizable | MutateAssets en AssetService |
Crea un YoutubeVideoAsset (youtube_video_id = video_id) para obtener un nombre de recurso de recurso (customers/{customer_id}/assets/{asset_id}). |
| 4. Vincula el recurso a campañas o anuncios | MutateAssetGroupAssets en AssetGroupAssetService o MutateAdGroupAds en AdGroupAdService |
Vincula el recurso a un AssetGroupAsset (field_type = YOUTUBE_VIDEO) de máximo rendimiento o a un DemandGenVideoResponsiveAdInfo (videos[].asset) de generación de demanda. |
Propiedad del canal
Cuando subes un video, puedes especificar el canal de YouTube de destino con
el channel_id campo en el YouTubeVideoUpload
recurso:
- Canal propiedad del anunciante (de marca): Proporciona el
channel_idde un canal de YouTube existente que sea propiedad del anunciante. Esto solo es compatible con el flujo de autenticación de usuarios y no se puede usar con cuentas de servicio. - Canal administrado por Google: Si se omite
channel_id, el video se sube a un canal de YouTube administrado por Google asociado con la cuenta de Google Ads.
Estados de carga
El ciclo de vida de una carga de video de YouTube se realiza un seguimiento con el campo state.
La YouTubeVideoUploadState
enumeración define los siguientes estados:
| Estado | Descripción |
|---|---|
PENDING |
Se está subiendo el video. |
UPLOADED |
El video se subió correctamente y YouTube lo está procesando. |
PROCESSED |
El video se procesó correctamente y está listo para usarse. |
FAILED |
No se pudo completar la carga ni el procesamiento. |
REJECTED |
Se rechazó el video por motivos de validación o de política. |
UNAVAILABLE |
El estado del video no está disponible. Es posible que se haya quitado de YouTube. |
Configuración de privacidad
El campo video_privacy controla quién puede ver el video subido. La
YouTubeVideoPrivacy
enumeración admite lo siguiente:
PUBLIC: El video está disponible para cualquier persona en YouTube. (Solo se permite para canales de marca).UNLISTED: El video no se puede buscar, pero cualquier persona con el vínculo puede verlo. Esta es la opción predeterminada y única para los canales administrados por Google.
Divulgación de contenido generativo
A partir de la versión 26, según reglamentaciones como la Ley de IA de la UE, los anunciantes pueden divulgar si el contenido de video subido incluye contenido generado por IA o contenido sintético.
El campo video_content_metadata en YouTubeVideoUpload contiene
VideoContentMetadata. Configura su campo anidado
generative_content_disclosure con la
YouTubeVideoUploadGenerativeContentDisclosure
enumeración:
| Valor | Descripción |
|---|---|
NON_GENERATIVE_CONTENT |
El anunciante divulgó que el video no se generó con IA. |
GENERATIVE_CONTENT |
El anunciante divulgó que el video se generó con IA. |
Subir un video
Para subir un video, debes usar una solicitud de varias partes al método CreateYouTubeVideoUpload. La solicitud contiene los metadatos de la carga y el archivo de video.
1. Inicia la carga
Crea un CreateYouTubeVideoUploadRequest con los siguientes campos:
| Campo | Requisito | Descripción y restricciones |
|---|---|---|
customer_id |
Obligatorio | Es el ID de cliente de Google Ads de 10 dígitos (sin guiones). |
you_tube_video_upload.video_title |
Obligatorio (INPUT_ONLY, IMMUTABLE) |
Es el título del video subido en YouTube (hasta 100 caracteres; no puede contener < ni >). |
you_tube_video_upload.video_description |
Opcional (INPUT_ONLY, IMMUTABLE) |
Es la descripción del video en YouTube (hasta 5,000 caracteres; no puede contener < ni >). |
you_tube_video_upload.channel_id |
Opcional (IMMUTABLE) |
Es el ID del canal de YouTube de destino de 24 caracteres (que comienza con UC) para un canal de marca propiedad del anunciante. Si se omite, se sube a un canal administrado por Google. |
you_tube_video_upload.video_privacy |
Opcional (mutable en canales de marca) | YouTubeVideoPrivacy configuración (UNLISTED predeterminado o PUBLIC para canales patrocinados propiedad del anunciante). |
you_tube_video_upload.video_content_metadata |
Opcional (INPUT_ONLY, IMMUTABLE) |
Disponible a partir de la versión 26: VideoContentMetadata con generative_content_disclosure configurado en un valor YouTubeVideoUploadGenerativeContentDisclosure (NON_GENERATIVE_CONTENT o GENERATIVE_CONTENT). |
Si usas una biblioteca cliente, llama al
CreateYouTubeVideoUpload
método, pasa tu archivo de video y la carga de video se controlará
de forma interna.
Java
String videoUploadResourceName; try (YouTubeVideoUploadServiceClient youTubeVideoUploadServiceClient = googleAdsClient.getLatestVersion().createYouTubeVideoUploadServiceClient()) { YouTubeVideoUpload youTubeVideoUpload = YouTubeVideoUpload.newBuilder() .setVideoTitle("Test Video") .setVideoDescription("Test Video Description") .setVideoPrivacy(YouTubeVideoPrivacy.UNLISTED) .build(); CreateYouTubeVideoUploadRequest createUploadRequest = CreateYouTubeVideoUploadRequest.newBuilder() .setCustomerId(Long.toString(customerId)) .setYouTubeVideoUpload(youTubeVideoUpload) .build(); CreateYouTubeVideoUploadResponse response = youTubeVideoUploadServiceClient.createYouTubeVideoUpload( createUploadRequest, () -> new FileInputStream(videoFile), null); videoUploadResourceName = response.getResourceName(); System.out.printf("Created YouTube video upload: %s%n", videoUploadResourceName); }
C#
YouTubeVideoUploadServiceClient ytService = client.GetService( Services.V26.YouTubeVideoUploadService); CreateYouTubeVideoUploadRequest createUploadRequest = new CreateYouTubeVideoUploadRequest() { CustomerId = customerId.ToString(), YouTubeVideoUpload = new YouTubeVideoUpload() { VideoTitle = "Test Video", VideoDescription = "Test Video Description", VideoPrivacy = YouTubeVideoPrivacy.Unlisted } }; string videoUploadResourceName; using (FileStream stream = File.OpenRead(videoFilePath)) { ResumableUploadSession<CreateYouTubeVideoUploadRequest, CreateYouTubeVideoUploadResponse> session = ytService.CreateYouTubeVideoUpload(); CreateYouTubeVideoUploadResponse response = session.BeginUploadAsync(createUploadRequest, stream).Result; videoUploadResourceName = response.ResourceName; Console.WriteLine($"Created YouTube video upload: {videoUploadResourceName}"); }
PHP
$youTubeVideoUploadServiceClient = $googleAdsClient->getYouTubeVideoUploadServiceClient(); $youTubeVideoUpload = new YouTubeVideoUpload([ 'video_title' => 'Test Video', 'video_description' => 'Test Video Description', 'video_privacy' => YouTubeVideoPrivacy::UNLISTED ]); $createYouTubeVideoUploadRequest = CreateYouTubeVideoUploadRequest::build( $customerId, $youTubeVideoUpload ); /** @var ResumableUpload $resumableUpload */ $resumableUpload = $youTubeVideoUploadServiceClient->createYouTubeVideoUpload( $createYouTubeVideoUploadRequest ); $stream = Utils::streamFor(fopen($videoFilePath, 'rb')); /** @var CreateYouTubeVideoUploadResponse $response */ $response = $resumableUpload->startUpload($stream); $videoUploadResourceName = $response->getResourceName(); printf("Created YouTube video upload: '%s'%s", $videoUploadResourceName, PHP_EOL);
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, ) ) video_upload_resource_name = response.resource_name print(f"Created YouTube video upload: {video_upload_resource_name}")
Ruby
video_upload = client.resource.you_tube_video_upload do |v| v.video_title = "Test Video" v.video_description = "Test Video Description" v.video_privacy = :UNLISTED end upload = client.service.you_tube_video_upload.create_you_tube_video_upload( customer_id: customer_id, you_tube_video_upload: video_upload, ) video_upload_resource_name = nil File.open(video_file_path, "rb") do |stream| response = upload.start( stream: stream, content_type: "application/octet-stream", ) video_upload_resource_name = response.resource_name puts "Created YouTube video upload: #{video_upload_resource_name}" end
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 "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')
Si usas REST, en la siguiente sección, se describe cómo administrar la carga de video.
2. Sube el video
Cuando se sube con REST, CreateYouTubeVideoUpload usa un protocolo de carga reanudable de dos pasos
:
- Inicia la sesión de carga: Envía una solicitud
POSTinicial alCreateYouTubeVideoUploadextremo de carga (/upload/v26/customers/{customer_id}/youTubeVideoUploads:create) conx-goog-upload-command: start(y, de manera opcional,x-goog-upload-header-content-lengthpara declarar el tamaño del archivo). La respuesta devuelve la URL de la sesión de carga en el encabezado de respuesta HTTPx-goog-upload-url, junto con metadatos como el tamaño de fragmento esperado. - Transmite y finaliza los bytes de video: Envía la carga útil de video binaria al extremo
x-goog-upload-urlconx-goog-upload-command: upload, finalize. Cuando finaliza la carga, la respuesta devuelve elresource_namecreado (customers/{customer_id}/youTubeVideoUploads/{video_upload_id}).
Para obtener una descripción completa de los encabezados HTTP que se usan en el protocolo de carga de video, consulta el siguiente ejemplo de código:
# 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. Recupera el estado de carga del video
Después de iniciar una carga de video, consulta su estado de procesamiento consultando los
campos seleccionables del you_tube_video_upload recurso
(resource_name, video_upload_id, channel_id, video_id, state, y
video_privacy) con GAQL hasta que state = 'PROCESSED' (los campos INPUT_ONLY no se
pueden seleccionar en GAQL):
Java
// Retrieve the metadata of the newly uploaded video. String query = String.format( "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 = '%s'", videoUploadResourceName); try (GoogleAdsServiceClient googleAdsServiceClient = googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { SearchGoogleAdsStreamRequest request = SearchGoogleAdsStreamRequest.newBuilder() .setCustomerId(Long.toString(customerId)) .setQuery(query) .build(); ServerStream<SearchGoogleAdsStreamResponse> stream = googleAdsServiceClient.searchStreamCallable().call(request); for (SearchGoogleAdsStreamResponse response : stream) { for (GoogleAdsRow googleAdsRow : response.getResultsList()) { YouTubeVideoUpload video = googleAdsRow.getYouTubeVideoUpload(); System.out.printf( "Video with ID %s was found in state %s.%n", video.getVideoId(), video.getState()); } } }
C#
// Retrieve the metadata of the newly uploaded video. string 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 = '{videoUploadResourceName}'"; GoogleAdsServiceClient gaService = client.GetService( Services.V26.GoogleAdsService); gaService.SearchStream(customerId.ToString(), query, delegate (SearchGoogleAdsStreamResponse resp) { foreach (GoogleAdsRow row in resp.Results) { Console.WriteLine( $"Video with ID {row.YouTubeVideoUpload.VideoId} was found in " + $"state {row.YouTubeVideoUpload.State}."); } } );
PHP
// Retrieve the metadata of the newly uploaded video. $query = sprintf( "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 = '%s'", $videoUploadResourceName ); $googleAdsServiceClient = $googleAdsClient->getGoogleAdsServiceClient(); $stream = $googleAdsServiceClient->searchStream( SearchGoogleAdsStreamRequest::build($customerId, $query) ); foreach ($stream->iterateAllElements() as $googleAdsRow) { /** @var GoogleAdsRow $googleAdsRow */ printf( "Video with ID '%s' was found in state '%s'.%s", $googleAdsRow->getYouTubeVideoUpload()->getVideoId(), YouTubeVideoUploadState::name($googleAdsRow->getYouTubeVideoUpload()->getState()), PHP_EOL ); }
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
# Retrieve the metadata of the newly uploaded video. query = <<~EOQ 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}' EOQ responses = client.service.google_ads.search_stream( customer_id: customer_id, query: query, ) responses.each do |batch| batch.results.each do |row| puts "Video with ID #{row.you_tube_video_upload.video_id} was found in " \ "state #{row.you_tube_video_upload.state}." end end
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
Administrar cargas de archivos
Una vez que se completa la carga de un video, puedes usarlo como recurso de video.
Usa el video subido
Después de que un video alcanza el estado PROCESSED, puedes encontrar su ID de video de YouTube de 11 caracteres en el campo video_id del recurso YouTubeVideoUpload.
Usa este video_id para crear un YoutubeVideoAsset con
MutateAssets y vincular el nombre de recurso de recurso resultante
(customers/{customer_id}/assets/{asset_id}) a tus campañas o anuncios:
Para crear el
YoutubeVideoAsset, pasayoutube_video_idaAssetService.MutateAssets:POST https://googleads.googleapis.com/v26/customers/{customer_id}/assets:mutate { "operations": [ { "create": { "name": "Product Launch Video", "youtubeVideoAsset": { "youtubeVideoId": "dQw4w9WgXcQ" } } } ] }Vincula el
Asseta unAssetGroupoAdGroupAd:Campaña de máximo rendimiento: Crea un
AssetGroupAssetconAssetGroupAssetService.MutateAssetGroupAssetsy configurafield_typecomoYOUTUBE_VIDEO:POST https://googleads.googleapis.com/v26/customers/{customer_id}/assetGroupAssets:mutate { "operations": [ { "create": { "assetGroup": "customers/{customer_id}/assetGroups/{asset_group_id}", "asset": "customers/{customer_id}/assets/{asset_id}", "fieldType": "YOUTUBE_VIDEO" } } ] }Campaña de generación de demanda: Haz referencia a
customers/{customer_id}/assets/{asset_id}en la listavideosde unDemandGenVideoResponsiveAdInfoobjeto cuando llames aAdGroupAdService.MutateAdGroupAds:POST https://googleads.googleapis.com/v26/customers/{customer_id}/adGroupAds:mutate { "operations": [ { "create": { "adGroup": "customers/{customer_id}/adGroups/{ad_group_id}", "status": "PAUSED", "ad": { "name": "Demand Gen Video Ad", "finalUrls": ["https://www.example.com"], "demandGenVideoResponsiveAd": { "videos": [ { "asset": "customers/{customer_id}/assets/{asset_id}" } ], "logoImages": [ { "asset": "customers/{customer_id}/assets/{logo_asset_id}" } ], "headlines": [ { "text": "Example Headline" } ], "longHeadlines": [ { "text": "Example Long Headline" } ], "descriptions": [ { "text": "Example Description" } ], "businessName": { "text": "Example Business" } } } } } ] }
Consulta los recursos
YOUTUBE_VIDEOexistentes conGoogleAdsService.SearchStream:SELECT asset.id, asset.resource_name, asset.name, asset.type, asset.youtube_video_asset.youtube_video_id, asset.youtube_video_asset.youtube_video_title FROM asset WHERE asset.type = 'YOUTUBE_VIDEO' AND asset.youtube_video_asset.youtube_video_id = '{video_id}'
Actualizar metadatos
Puedes actualizar la configuración de privacidad de un video subido a través de esta API con
el UpdateYouTubeVideoUpload método y update_mask
configurado como "video_privacy". Solo se puede actualizar el campo video_privacy (PUBLIC o UNLISTED, para videos subidos a un canal patrocinado propiedad del anunciante) después de la creación; video_title, video_description, channel_id y video_content_metadata son inmutables.
Quitar cargas
Si necesitas borrar videos subidos con la API de Google Ads, pasa sus
customers/{customer_id}/youTubeVideoUploads/{video_upload_id} nombres de recursos
en el resource_names campo del
RemoveYouTubeVideoUpload método. Esto quita el video de la biblioteca de recursos de Google Ads y de YouTube.