Tải lên video

YouTubeVideoUploadService cho phép bạn tải video lên YouTube ngay thông qua Google Ads API. Sau đó, bạn có thể sử dụng những video này để tạo thành phần video trong nhiều loại quảng cáo, chẳng hạn như chiến dịch Tối đa hoá hiệu suất hoặc chiến dịch Tạo nhu cầu.

Dịch vụ này đơn giản hoá quy trình tạo quảng cáo dạng video bằng cách xử lý quy trình tải lên YouTube, đảm bảo rằng video được liên kết chính xác với tài khoản của bạn.

Khái niệm chính

Trước khi bắt đầu, bạn cần hiểu rõ cách quản lý video tải lên và các trạng thái mà video có thể trải qua.

Quy trình công việc toàn diện

Để tải tệp video lên và phân phát tệp đó trong quảng cáo, bạn cần thực hiện 4 bước tuần tự:

Bước Dịch vụ và phương thức Tóm tắt
1. Bắt đầu và tải byte video lên CreateYouTubeVideoUpload vào YouTubeVideoUploadService Tải siêu dữ liệu video và tệp nhị phân lên để tạo tài nguyên YouTubeVideoUpload (customers/{customer_id}/youTubeVideoUploads/{video_upload_id}).
2. Trạng thái xử lý cuộc thăm dò ý kiến SearchStream vào GoogleAdsService Truy vấn you_tube_video_upload cho đến state = 'PROCESSED' và video_id YouTube gồm 11 ký tự được điền sẵn.
3. Tạo thành phần video có thể sử dụng lại MutateAssets vào AssetService Tạo YoutubeVideoAsset (youtube_video_id = video_id) để lấy tên tài nguyên thành phần (customers/{customer_id}/assets/{asset_id}).
4. Liên kết thành phần với chiến dịch hoặc quảng cáo MutateAssetGroupAssets trên AssetGroupAssetService hoặc MutateAdGroupAds trên AdGroupAdService Liên kết thành phần với chiến dịch Tối đa hoá hiệu suất AssetGroupAsset (field_type = YOUTUBE_VIDEO) hoặc chiến dịch Tạo nhu cầu DemandGenVideoResponsiveAdInfo (videos[].asset).

Quyền sở hữu kênh

Khi tải video lên, bạn có thể chỉ định kênh YouTube đích bằng cách sử dụng trường channel_id trong tài nguyên YouTubeVideoUpload:

  • Kênh thuộc sở hữu của nhà quảng cáo (kênh thương hiệu): Cung cấp channel_id của một kênh YouTube hiện có thuộc sở hữu của nhà quảng cáo. Tính năng này chỉ được hỗ trợ với quy trình xác thực người dùng; không thể sử dụng tính năng này với tài khoản dịch vụ.
  • Kênh do Google quản lý: Nếu bạn bỏ qua channel_id, video sẽ được tải lên một kênh YouTube do Google quản lý và liên kết với tài khoản Google Ads.

Trạng thái tải lên

Vòng đời của một video tải lên YouTube được theo dõi bằng trường state. Enum YouTubeVideoUploadState xác định các trạng thái sau:

Tiểu bang Mô tả
PENDING Video đang được tải lên.
UPLOADED Video đã được tải lên thành công và đang được YouTube xử lý.
PROCESSED Video đã được xử lý xong và sẵn sàng để sử dụng.
FAILED Không thể hoàn tất quá trình tải lên hoặc xử lý.
REJECTED Video bị từ chối do không xác thực được hoặc vi phạm chính sách.
UNAVAILABLE Không có trạng thái của video; video có thể đã bị gỡ bỏ khỏi YouTube.

Chế độ cài đặt quyền riêng tư

Trường video_privacy kiểm soát những người có thể xem video đã tải lên. Enum YouTubeVideoPrivacy hỗ trợ:

  • PUBLIC: Bất kỳ ai trên YouTube cũng có thể xem video này. (Chỉ được phép đối với kênh thương hiệu).
  • UNLISTED: Video không thể tìm kiếm được nhưng bất kỳ ai có đường liên kết đều có thể xem. Đây là lựa chọn mặc định và duy nhất cho các kênh do Google quản lý.

Yêu cầu về tiêu đề và nội dung mô tả

Khi tạo một video tải lên, bạn có thể chỉ định siêu dữ liệu bằng cách sử dụng các trường video_title và video_description trong tài nguyên YouTubeVideoUpload:

  • video_title: Bắt buộc. Tiêu đề không được vượt quá 100 ký tự và không được chứa các ký tự không hợp lệ (dấu ngoặc nhọn < hoặc >). Bạn chỉ có thể đặt tiêu đề khi tạo video tải lên và không thể thay đổi tiêu đề sau khi tạo.
  • video_description: Không bắt buộc. Nội dung mô tả không được vượt quá 5.000 ký tự và không được chứa các ký tự không hợp lệ (dấu ngoặc nhọn < hoặc >). Bạn chỉ có thể đặt nội dung mô tả khi tạo video tải lên và không thể thay đổi nội dung này sau khi tạo.

Cả hai trường đều không thể thay đổi sau khi tạo. Việc đưa video_title hoặc video_description vào mặt nạ cập nhật của yêu cầu UpdateYouTubeVideoUpload sẽ không thành công và trả về lỗi FieldError.IMMUTABLE_FIELD.

Để biết thêm thông tin về định dạng tiêu đề và nội dung mô tả trên YouTube cũng như các ký tự không hợp lệ, hãy xem Trung tâm trợ giúp của YouTube.

Thông tin công bố về nội dung do AI tạo sinh tạo ra

Kể từ phiên bản 26, theo các quy định như Đạo luật AI của Liên minh Châu Âu, nhà quảng cáo có thể tiết lộ liệu nội dung video đã tải lên có chứa nội dung nghe nhìn do AI tạo hoặc nội dung nghe nhìn tổng hợp hay không.

Trường video_content_metadata trong YouTubeVideoUpload chứa VideoContentMetadata. Đặt trường generative_content_disclosure lồng nhau bằng cách sử dụng enum YouTubeVideoUploadGenerativeContentDisclosure:

Giá trị Mô tả
NON_GENERATIVE_CONTENT Nhà quảng cáo đã công bố rằng video này không phải do AI tạo.
GENERATIVE_CONTENT Nhà quảng cáo đã công bố rằng video này do AI tạo.

Tải video lên

Để tải video lên, bạn phải sử dụng yêu cầu nhiều phần cho phương thức CreateYouTubeVideoUpload. Yêu cầu này chứa cả siêu dữ liệu cho nội dung tải lên và tệp video.

1. Bắt đầu tải lên

Tạo một CreateYouTubeVideoUploadRequest có các trường sau:

Trường Yêu cầu Nội dung mô tả và các quy tắc ràng buộc
customer_id Bắt buộc Mã khách hàng Google Ads gồm 10 chữ số (không có dấu gạch nối).
you_tube_video_upload.video_title Bắt buộc (INPUT_ONLY, IMMUTABLE) Tiêu đề của video được tải lên YouTube (tối đa 100 ký tự; không được chứa < hoặc >).
you_tube_video_upload.video_description Không bắt buộc (INPUT_ONLY, IMMUTABLE) Nội dung mô tả video trên YouTube (tối đa 5.000 ký tự; không được chứa < hoặc >).
you_tube_video_upload.channel_id Không bắt buộc (IMMUTABLE) Mã nhận dạng kênh YouTube đích gồm 24 ký tự (bắt đầu bằng UC) cho kênh thương hiệu thuộc sở hữu của nhà quảng cáo. Nếu bạn bỏ qua, video sẽ được tải lên một kênh do Google quản lý.
you_tube_video_upload.video_privacy Không bắt buộc (có thể thay đổi trên kênh thương hiệu) Chế độ cài đặt YouTubeVideoPrivacy (UNLISTED là mặc định hoặc PUBLIC cho kênh thương hiệu do nhà quảng cáo sở hữu).
you_tube_video_upload.video_content_metadata Không bắt buộc (INPUT_ONLY, IMMUTABLE) Có trong phiên bản 26 trở lên: VideoContentMetadata với generative_content_disclosure được đặt thành giá trị YouTubeVideoUploadGenerativeContentDisclosure (NON_GENERATIVE_CONTENT hoặc GENERATIVE_CONTENT).

Nếu bạn đang sử dụng thư viện ứng dụng, hãy gọi phương thức CreateYouTubeVideoUpload, truyền tệp video của bạn và quá trình tải video lên sẽ được xử lý nội bộ.

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')
      

Nếu bạn đang sử dụng REST, phần sau đây sẽ mô tả cách quản lý quá trình tải video lên.

2. Tải video lên

Khi tải lên bằng REST, CreateYouTubeVideoUpload sử dụng giao thức tải lên tiếp nối gồm hai bước:

  1. Bắt đầu phiên tải lên: Gửi yêu cầu POST ban đầu đến điểm cuối tải lên CreateYouTubeVideoUpload (/upload/v26/customers/{customer_id}/youTubeVideoUploads:create) bằng x-goog-upload-command: start (và x-goog-upload-header-content-length (không bắt buộc) để khai báo kích thước tệp). Phản hồi sẽ trả về URL của phiên tải lên trong tiêu đề phản hồi HTTP x-goog-upload-url, cùng với siêu dữ liệu như kích thước phân đoạn dự kiến.
  2. Truyền trực tuyến và hoàn tất các byte video: Gửi tải trọng video nhị phân đến điểm cuối x-goog-upload-url bằng x-goog-upload-command: upload, finalize. Khi quá trình tải lên hoàn tất, phản hồi sẽ trả về resource_name đã tạo (customers/{customer_id}/youTubeVideoUploads/{video_upload_id}).

Để xem nội dung mô tả đầy đủ về các tiêu đề HTTP được dùng trong giao thức tải video lên, hãy tham khảo mã ví dụ sau:

# 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. Truy xuất trạng thái tải video lên

Sau khi bắt đầu tải video lên, hãy thăm dò trạng thái xử lý của video bằng cách truy vấn các trường có thể chọn của tài nguyên you_tube_video_upload (resource_name, video_upload_id, channel_id, video_id, state và video_privacy) bằng GAQL cho đến khi state = 'PROCESSED' (không thể chọn các trường INPUT_ONLY trong 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
      

Quản lý mục tải lên

Sau khi tải video lên, bạn có thể sử dụng video đó làm thành phần video.

Sử dụng video đã tải lên

Sau khi video đạt đến trạng thái PROCESSED, bạn có thể tìm thấy mã video gồm 11 ký tự trên YouTube trong trường video_id của tài nguyên YouTubeVideoUpload.

Sử dụng video_id này để tạo YoutubeVideoAsset bằng MutateAssets và liên kết tên tài nguyên thành phần thu được (customers/{customer_id}/assets/{asset_id}) với chiến dịch hoặc quảng cáo của bạn:

  1. Tạo YoutubeVideoAsset bằng cách truyền youtube_video_id đến AssetService.MutateAssets:

    POST https://googleads.googleapis.com/v26/customers/{customer_id}/assets:mutate
    {
      "operations": [
        {
          "create": {
            "name": "Product Launch Video",
            "youtubeVideoAsset": {
              "youtubeVideoId": "dQw4w9WgXcQ"
            }
          }
        }
      ]
    }
    
  2. Liên kết Asset với AssetGroup hoặc AdGroupAd:

    • Tối đa hoá hiệu suất: Tạo AssetGroupAsset bằng AssetGroupAssetService.MutateAssetGroupAssets, trong đó field_type được đặt thành YOUTUBE_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"
            }
          }
        ]
      }
      
    • Tạo nhu cầu: Tham chiếu customers/{customer_id}/assets/{asset_id} trong danh sách videos của đối tượng DemandGenVideoResponsiveAdInfo khi gọi AdGroupAdService.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"
                  }
                }
              }
            }
          }
        ]
      }
      
  3. Truy vấn các thành phần YOUTUBE_VIDEO hiện có bằng cách sử dụng GoogleAdsService.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}'
    

Cập nhật siêu dữ liệu

Bạn có thể cập nhật chế độ cài đặt quyền riêng tư của video được tải lên thông qua API này bằng cách sử dụng phương thức UpdateYouTubeVideoUpload với update_mask được đặt thành "video_privacy". Chỉ có thể cập nhật trường video_privacy (PUBLIC hoặc UNLISTED, đối với video được tải lên kênh thương hiệu do nhà quảng cáo sở hữu) sau khi tạo; video_title, video_description, channel_id và video_content_metadata không thể thay đổi. Nếu bạn thêm video_title hoặc video_description vào mặt nạ cập nhật, thì thao tác này sẽ không thành công và trả về lỗi FieldError.IMMUTABLE_FIELD.

Xoá video tải lên

Nếu bạn cần xoá video đã tải lên bằng Google Ads API, hãy truyền customers/{customer_id}/youTubeVideoUploads/{video_upload_id} tên tài nguyên vào trường resource_names của phương thức RemoveYouTubeVideoUpload. Thao tác này sẽ xoá video khỏi cả thư viện thành phần của Google Ads và YouTube.