Before you create a Demand Gen campaign, it's important to import all of the
assets you plan to use in the campaign. You can always come back and add assets
later, but you need a set of assets to even begin.

Check out the Demand Gen [asset specs and best practices guide](https://support.google.com/google-ads/answer/13704860) while
planning your campaign.

Image and video assets are the primary asset types, and this guide will
demonstrate how to upload each of these. These principles can be extended to
other asset types as well. No matter what type of asset you're making, use
[`AssetOperation`](https://developers.google.com/google-ads/api/reference/rpc/v26/AssetOperation) to create it.

Assets can be created using [`AdsApp`](https://developers.google.com/google-ads/scripts/docs/reference/adsapp/adsapp_adassets) without using mutate, but for the sake
of consistency, this guide does it the same way as all the rest of the
operations. Note that you can and should reuse existing assets if you already
have some available. So while it's required that you have assets to create a
Demand Gen campaign, it might not be strictly required that you *create* them as
part of the campaign creation process.

## Image assets

Image assets are uploaded in a [base-64 encoded](https://en.wikipedia.org/wiki/Base64) format. Since you can't
upload images directly into Google Ads scripts, you have a choice of two different
approaches for getting the image data and encoding it for the upload.

To fetch an image from Google Drive, first you'll need its [ID](https://developers.google.com/apps-script/reference/drive/file#getId()), which is the
best way to uniquely identify the image. One way to get the ID is to copy the
shareable link from the Google Drive UI and extract the ID. You can also fetch a
series of files programmatically and select the ones you want to upload. This
code demonstrates how to upload a single image with a known ID:

    const file = DriveApp.getFileById(fileId);
    const imageAsset =  {
      "assetOperation": {
        "create": {
          "resourceName": `customers/${customerId}/assets/${getNextTempId()}`,
          "name": "Marketing Logo",
          "type": "IMAGE",
          "imageAsset": {
            "data": Utilities.base64Encode(file.getBlob().getBytes())
          }
        }
      }
    }

Alternatively, you can fetch an image hosted on a web server by its URL by using
`UrlFetchApp`:

    const file = UrlFetchApp.fetch(imageUrl);

You can then call `getBlob` on this file just as you would with a Drive file,
so the operation construction is identical to the steps for a Google Drive file.

## Video assets

Video assets are managed through YouTube videos. If you're
uploading assets as part of the campaign creation process, use a
[temporary ID](https://developers.google.com/google-ads/scripts/docs/elements/ids#temporary_ids). Otherwise, make a note of the returned resource name to use
in a future operation when you need to reference the asset to add it to an asset
group.

    const videoAsset = {
      "assetOperation": {
        "create": {
          "resourceName": `customers/${customerId}/assets/${getNextTempId()}`,
          "name": "Marketing video",
          "type": "YOUTUBE_VIDEO",
          "youtube_video_asset": {
            "youtube_video_title": "Demand Gen video",
            "youtube_video_id": "123456789"
          }
        }
      }
    }
    operations.push(videoAsset);