Performance Max for travel goals campaigns let you easily create ads for hotel properties that serve across Google channels such as Search, Display, Video, and Discover. In addition to all the benefits you get from using Performance Max campaigns—such as automatic budget allocation across channels, final URL expansion, and so on—Performance Max for travel goals can increase your ad coverage on Search, and also suggest assets to be created as an asset group for each of your hotel properties.
Unlike Hotel Ads, you don't need to have access to a Hotel Center account in order to use Performance Max for travel goals.
Create a Performance Max for travel goals campaign
The steps for creating a Performance Max for travel goals campaign are as follows:
- Create an asset set, assets for all your hotel properties, and asset set assets to link the created asset set and assets.
- (Recommended) Get suggested assets that you can use to create an asset group.
- Create a Performance Max campaign using the asset set and the suggested assets.
Create asset entities for your hotel properties
Create a hotel property asset set of type
HOTEL_PROPERTY
by settingAssetSet.type
toAssetSetType.HOTEL_PROPERTY
. You'll use the resource name of the created asset set in the later steps.Java
private String createHotelAssetSet(GoogleAdsClient googleAdsClient, long customerId) { // Creates an asset set operation for a hotel property asset set. AssetSetOperation assetSetOperation = AssetSetOperation.newBuilder() .setCreate( AssetSet.newBuilder() .setName( "My Hotel propery asset set #" + CodeSampleHelper.getPrintableDateTime()) .setType(AssetSetType.HOTEL_PROPERTY)) .build(); try (AssetSetServiceClient assetSetServiceClient = googleAdsClient.getLatestVersion().createAssetSetServiceClient()) { MutateAssetSetsResponse mutateAssetSetsResponse = assetSetServiceClient.mutateAssetSets( Long.toString(customerId), ImmutableList.of(assetSetOperation)); String assetSetResourceName = mutateAssetSetsResponse.getResults(0).getResourceName(); System.out.printf("Created an asset set with resource name: '%s'%n", assetSetResourceName); return assetSetResourceName; } }
C#
This example is not yet available in C#; you can take a look at the other languages.
PHP
private static function createHotelAssetSet( GoogleAdsClient $googleAdsClient, int $customerId ): string { // Creates an asset set operation for a hotel property asset set. $assetSetOperation = new AssetSetOperation([ // Creates a hotel property asset set. 'create' => new AssetSet([ 'name' => 'My Hotel propery asset set #' . Helper::getPrintableDatetime(), 'type' => AssetSetType::HOTEL_PROPERTY ]) ]); // Issues a mutate request to add a hotel asset set and prints its information. $assetSetServiceClient = $googleAdsClient->getAssetSetServiceClient(); $response = $assetSetServiceClient->mutateAssetSets($customerId, [$assetSetOperation]); $assetSetResourceName = $response->getResults()[0]->getResourceName(); printf("Created an asset set with resource name: '%s'.%s", $assetSetResourceName, PHP_EOL); return $assetSetResourceName; }
Python
This example is not yet available in Python; you can take a look at the other languages.
Ruby
# Creates a hotel property asset set. def create_hotel_asset_set(client, customer_id) operation = client.operation.create_resource.asset_set do |asset_set| asset_set.name = "My Hotel propery asset set #{Time.now}" asset_set.type = :HOTEL_PROPERTY end # Sends the mutate request. response = client.service.asset_set.mutate_asset_sets( customer_id: customer_id, operations: [operation] ) # Prints some information about the response. response.results.first.resource_name end
Perl
This example is not yet available in Perl; you can take a look at the other languages.
For each of your hotel properties, do the following:
Create an asset by setting
Asset.hotel_property_asset
to an object ofHotelPropertyAsset
.For simplicity, our code example creates only one hotel property asset.
Set
place_id
of the createdHotelPropertyAsset
object to the place ID of the hotel property. The place ID is a unique ID that identifies a place on Google Maps. You can look up your property with the place ID finder.Create an asset set asset to link the above asset set with the asset by creating a new
AssetSetAsset
and setting itsasset_set
to the resource name of the created asset set andasset
to the resource name of the created hotel property asset.
Java
private String createHotelAsset( GoogleAdsClient googleAdsClient, long customerId, String placeId, String hotelPropertyAssetSetResourceName) { // Uses the GoogleAdService to create an asset and asset set asset in a single request. List<MutateOperation> mutateOperations = new ArrayList<>(); String assetResourceName = ResourceNames.asset(customerId, ASSET_TEMPORARY_ID); // Creates a mutate operation for a hotel property asset. Asset hotelPropertyAsset = Asset.newBuilder() .setResourceName(assetResourceName) .setHotelPropertyAsset(HotelPropertyAsset.newBuilder().setPlaceId(placeId)) .build(); mutateOperations.add( MutateOperation.newBuilder() .setAssetOperation(AssetOperation.newBuilder().setCreate(hotelPropertyAsset)) .build()); // Creates a mutate operation for an asset set asset. AssetSetAsset assetSetAsset = AssetSetAsset.newBuilder() .setAsset(assetResourceName) .setAssetSet(hotelPropertyAssetSetResourceName) .build(); mutateOperations.add( MutateOperation.newBuilder() .setAssetSetAssetOperation(AssetSetAssetOperation.newBuilder().setCreate(assetSetAsset)) .build()); // Issues a mutate request to create all entities. try (GoogleAdsServiceClient googleAdsServiceClient = googleAdsClient.getLatestVersion().createGoogleAdsServiceClient()) { MutateGoogleAdsResponse mutateGoogleAdsResponse = googleAdsServiceClient.mutate(Long.toString(customerId), mutateOperations); System.out.println("Created the following entities for the hotel asset:"); printResponseDetails(mutateGoogleAdsResponse); // Returns the created asset resource name, which will be used later to create an asset // group. Other resource names are not used later. return mutateGoogleAdsResponse .getMutateOperationResponses(0) .getAssetResult() .getResourceName(); } }
C#
This example is not yet available in C#; you can take a look at the other languages.
PHP
private static function createHotelAsset( GoogleAdsClient $googleAdsClient, int $customerId, string $placeId, string $assetSetResourceName ): string { // We use the GoogleAdService to create an asset and asset set asset in a single // request. $operations = []; $assetResourceName = ResourceNames::forAsset($customerId, self::ASSET_TEMPORARY_ID); // Creates a mutate operation for a hotel property asset. $operations[] = new MutateOperation([ 'asset_operation' => new AssetOperation([ // Creates a hotel property asset. 'create' => new Asset([ 'resource_name' => $assetResourceName, // Creates a hotel property asset for the place ID. 'hotel_property_asset' => new HotelPropertyAsset(['place_id' => $placeId]), ]) ]) ]); // Creates a mutate operation for an asset set asset. $operations[] = new MutateOperation([ 'asset_set_asset_operation' => new AssetSetAssetOperation([ // Creates an asset set asset. 'create' => new AssetSetAsset([ 'asset' => $assetResourceName, 'asset_set' => $assetSetResourceName ]) ]) ]); // Issues a mutate request to create all entities. $googleAdsService = $googleAdsClient->getGoogleAdsServiceClient(); /** @var MutateGoogleAdsResponse $mutateGoogleAdsResponse */ $mutateGoogleAdsResponse = $googleAdsService->mutate($customerId, $operations); print "Created the following entities for the hotel asset:" . PHP_EOL; self::printResponseDetails($mutateGoogleAdsResponse); // Returns the created asset resource name, which will be used later to create an asset // group. Other resource names are not used later. return $mutateGoogleAdsResponse->getMutateOperationResponses()[0]->getAssetResult() ->getResourceName(); }
Python
This example is not yet available in Python; you can take a look at the other languages.
Ruby
# Creates a hotel property asset using the specified place ID. # The place ID must belong to a hotel property. Then, links it to the # specified asset set. # See https://developers.google.com/places/web-service/place-id to search for a # hotel place ID. def create_hotel_asset( client, customer_id, place_id, hotel_property_asset_set_resource_name ) asset_operation = client.operation.create_resource.asset do |asset| asset.name = 'Ad Media Bundle' asset.hotel_property_asset = client.resource.hotel_property_asset do |hotel_asset| hotel_asset.place_id = place_id end end # Send the mutate request. response = client.service.asset.mutate_assets( customer_id: customer_id, operations: [asset_operation] ) asset_resource_name = response.results.first.resource_name # Creates a mutate operation for an asset set asset. asset_set_asset_operation = client.operation.create_resource.asset_set_asset do |asa| asa.asset = asset_resource_name asa.asset_set = hotel_property_asset_set_resource_name end # Sends the mutate request. response = client.service.asset_set_asset.mutate_asset_set_assets( customer_id: customer_id, operations: [asset_set_asset_operation] ) asset_resource_name end
Perl
This example is not yet available in Perl; you can take a look at the other languages.
Get suggested assets that you can use to create an asset group
You can use
TravelAssetSugestionService.SuggestTravelAssets
to get suggested assets for your hotel properties. Once you get the suggestions,
you can use them to create assets in the asset group in the next step.
Java
private HotelAssetSuggestion getHotelAssetSuggestion( GoogleAdsClient googleAdsClient, long customerId, String placeId) { try (TravelAssetSuggestionServiceClient travelAssetSuggestionServiceClient = googleAdsClient.getLatestVersion().createTravelAssetSuggestionServiceClient()) { // Sends a request to suggest assets to be created as an asset group for the Performance Max // for travel goals campaign. SuggestTravelAssetsResponse suggestTravelAssetsResponse = travelAssetSuggestionServiceClient.suggestTravelAssets( SuggestTravelAssetsRequest.newBuilder() .setCustomerId(Long.toString(customerId)) // Uses 'en-US' as an example. It can be any language specifications in BCP 47 // format. .setLanguageOption("en-US") // The service accepts several place IDs. We use only one here for demonstration. .addPlaceId(placeId) .build()); System.out.printf("Fetched a hotel asset suggestion for the place ID '%s'.%n", placeId); return suggestTravelAssetsResponse.getHotelAssetSuggestions(0); } }
C#
This example is not yet available in C#; you can take a look at the other languages.
PHP
private static function getHotelAssetSuggestion( GoogleAdsClient $googleAdsClient, int $customerId, string $placeId ): HotelAssetSuggestion { // Send a request to suggest assets to be created as an asset group for the Performance Max // for travel goals campaign. $travelAssetSuggestionServiceClient = $googleAdsClient->getTravelAssetSuggestionServiceClient(); $response = $travelAssetSuggestionServiceClient->suggestTravelAssets( $customerId, // Uses 'en-US' as an example. It can be any language specifications in BCP 47 format. 'en-US', // The service accepts several place IDs. We use only one here for demonstration. ['placeId' => [$placeId]] ); printf("Fetched a hotel asset suggestion for the place ID '%s'.%s", $placeId, PHP_EOL); return $response->getHotelAssetSuggestions()[0]; }
Python
This example is not yet available in Python; you can take a look at the other languages.
Ruby
def get_hotel_asset_suggestion(client, customer_id, place_id) response = client.service.travel_asset_suggestion.suggest_travel_assets( customer_id: customer_id, language_option: 'en-US', place_id: [place_id] ) response.hotel_asset_suggestions.first end
Perl
This example is not yet available in Perl; you can take a look at the other languages.
Caveats
- This method works on a best-effort basis, so you might not get any suggestions.
- The service might not return all the required assets you need to create an asset group. In that case, create your own assets to fulfill the requirements.
Create a Performance Max campaign using the asset set and the suggested assets
Since this is a subtype of a Performance Max campaign, it has basic Performance Max requirements and restrictions, such as minimum asset requirements and the requirement that its campaign budget cannot be shared.
In general, you can follow most of the steps to create a Performance Max campaign. The differences worth noting are the following:
When creating a campaign, you need to also specify the
Campaign.hotel_property_asset_set
to the resource name of the asset set created in the first step.Java
private MutateOperation createCampaignOperation( long customerId, String hotelPropertyAssetSetResourceName) { Campaign performanceMaxCampaign = Campaign.newBuilder() .setName("Performance Max for travel goals campaign #" + getPrintableDateTime()) // Sets the campaign status as PAUSED. The campaign is the only entity in // the mutate request that should have its status set. .setStatus(CampaignStatus.PAUSED) // All Performance Max campaigns have an advertising_channel_type of // PERFORMANCE_MAX. The advertising_channel_sub_type should not be set. .setAdvertisingChannelType(AdvertisingChannelType.PERFORMANCE_MAX) // To create a Performance Max for travel goals campaign, you need to set // `hotel_property_asset_set`. .setHotelPropertyAssetSet(hotelPropertyAssetSetResourceName) // Bidding strategy must be set directly on the campaign. // Setting a portfolio bidding strategy by resource name is not supported. // Max Conversion and Maximize Conversion Value are the only strategies // supported for Performance Max campaigns. // An optional ROAS (Return on Advertising Spend) can be set for // maximize_conversion_value. The ROAS value must be specified as a ratio in // the API. It is calculated by dividing "total value" by "total spend". // For more information on Maximize Conversion Value, see the support // article: http://support.google.com/google-ads/answer/7684216. // A targetRoas of 3.5 corresponds to a 350% return on ad spend. .setMaximizeConversionValue( MaximizeConversionValue.newBuilder().setTargetRoas(3.5).build()) // Assigns the resource name with a temporary ID. .setResourceName(ResourceNames.campaign(customerId, CAMPAIGN_TEMPORARY_ID)) // Sets the budget using the given budget resource name. .setCampaignBudget(ResourceNames.campaignBudget(customerId, BUDGET_TEMPORARY_ID)) // Optional fields. .setStartDate(new DateTime().plusDays(1).toString("yyyyMMdd")) .setEndDate(new DateTime().plusDays(365).toString("yyyyMMdd")) .build(); return MutateOperation.newBuilder() .setCampaignOperation( CampaignOperation.newBuilder().setCreate(performanceMaxCampaign).build()) .build(); }
C#
This example is not yet available in C#; you can take a look at the other languages.
PHP
private static function createCampaignOperation( int $customerId, string $hotelPropertyAssetSetResourceName ): MutateOperation { // Creates a mutate operation that creates a campaign. return new MutateOperation([ 'campaign_operation' => new CampaignOperation([ 'create' => new Campaign([ 'name' => 'Performance Max for travel goals campaign #' . Helper::getPrintableDatetime(), // Assigns the resource name with a temporary ID. 'resource_name' => ResourceNames::forCampaign( $customerId, self::CAMPAIGN_TEMPORARY_ID ), // Sets the budget using the given budget resource name. 'campaign_budget' => ResourceNames::forCampaignBudget( $customerId, self::BUDGET_TEMPORARY_ID ), // The campaign is the only entity in the mutate request that should have its // status set. // Recommendation: Set the campaign to PAUSED when creating it to prevent // the ads from immediately serving. 'status' => CampaignStatus::PAUSED, // Performance Max campaigns have an advertising_channel_type of // PERFORMANCE_MAX. The advertising_channel_sub_type should not be set. 'advertising_channel_type' => AdvertisingChannelType::PERFORMANCE_MAX, // To create a Performance Max for travel goals campaign, you need to set // `hotel_property_asset_set`. 'hotel_property_asset_set' => $hotelPropertyAssetSetResourceName, // Bidding strategy must be set directly on the campaign. // Setting a portfolio bidding strategy by resource name is not supported. // Max Conversion and Maximize Conversion Value are the only strategies // supported for Performance Max campaigns. // An optional ROAS (Return on Advertising Spend) can be set for // maximize_conversion_value. The ROAS value must be specified as a ratio in // the API. It is calculated by dividing "total value" by "total spend". // For more information on Maximize Conversion Value, see the support // article: https://support.google.com/google-ads/answer/7684216. // A target_roas of 3.5 corresponds to a 350% return on ad spend. 'maximize_conversion_value' => new MaximizeConversionValue([ 'target_roas' => 3.5 ]) ]) ]) ]); }
Python
This example is not yet available in Python; you can take a look at the other languages.
Ruby
# Creates a MutateOperation that creates a new Performance Max campaign. # # A temporary ID will be assigned to this campaign so that it can # be referenced by other objects being created in the same Mutate request. def create_performance_max_campaign_operation( client, customer_id, hotel_property_asset_set_resource_name ) client.operation.mutate do |m| m.campaign_operation = client.operation.create_resource.campaign do |c| c.name = "Performance Max for Travel Goals #{SecureRandom.uuid}" # Set the campaign status as PAUSED. The campaign is the only entity in # the mutate request that should have its status set. c.status = :PAUSED # All Performance Max campaigns have an advertising_channel_type of # PERFORMANCE_MAX. The advertising_channel_sub_type should not be set. c.advertising_channel_type = :PERFORMANCE_MAX # To create a Performance Max for travel goals campaign, you need to set hotel_property_asset_set c.hotel_property_asset_set = hotel_property_asset_set_resource_name # Bidding strategy must be set directly on the campaign. # Setting a portfolio bidding strategy by resource name is not supported. # Max Conversion and Maximize Conversion Value are the only strategies # supported for Performance Max campaigns. # An optional ROAS (Return on Advertising Spend) can be set for # maximize_conversion_value. The ROAS value must be specified as a ratio # in the API. It is calculated by dividing "total value" by "total spend". # For more information on Maximize Conversion Value, see the support # article: http://support.google.com/google-ads/answer/7684216. # A target_roas of 3.5 corresponds to a 350% return on ad spend. c.bidding_strategy_type = :MAXIMIZE_CONVERSION_VALUE c.maximize_conversion_value = client.resource.maximize_conversion_value do |mcv| mcv.target_roas = 3.5 end # Assign the resource name with a temporary ID. c.resource_name = client.path.campaign( customer_id, PERFORMANCE_MAX_CAMPAIGN_TEMPORARY_ID ) # Set the budget using the given budget resource name. c.campaign_budget = client.path.campaign_budget(customer_id, BUDGET_TEMPORARY_ID) end end end
Perl
This example is not yet available in Perl; you can take a look at the other languages.
Instead of creating an asset group from scratch, you can now use the suggestion from
TravelAssetSugestionService.SuggestTravelAssets
when creating the asset group. You need to add more assets to fulfill the minimum asset requirements of Performance Max if the suggested assets are not enough.You need to link all the hotel property assets to the asset group you create to experience Performance Max for travel goals. Without these links, the campaign will be a regular Performance Max campaign.
Java
// Link the previously created hotel property asset to the asset group. In the real-world // scenario, you'd need to do this step several times for each hotel property asset. AssetGroupAsset hotelProperyAssetGroupAsset = AssetGroupAsset.newBuilder() .setAsset(hotelPropertyAssetResourceName) .setAssetGroup(assetGroupResourceName) .setFieldType(AssetFieldType.HOTEL_PROPERTY) .build(); // Adds an operation to link the hotel property asset to the asset group. mutateOperations.add( MutateOperation.newBuilder() .setAssetGroupAssetOperation( AssetGroupAssetOperation.newBuilder().setCreate(hotelProperyAssetGroupAsset)) .build());
C#
This example is not yet available in C#; you can take a look at the other languages.
PHP
// Link the previously created hotel property asset to the asset group. In the real-world // scenario, you'd need to do this step several times for each hotel property asset. $operations[] = new MutateOperation([ 'asset_group_asset_operation' => new AssetGroupAssetOperation([ 'create' => new AssetGroupAsset([ 'asset' => $hotelPropertyAssetResourceName, 'asset_group' => $assetGroupResourceName, 'field_type' => AssetFieldType::HOTEL_PROPERTY ]) ]) ]);
Python
This example is not yet available in Python; you can take a look at the other languages.
Ruby
# Link the previously created hotel property asset to the asset group. # In the real-world scenario, you'd need to do this step several times for # each hotel property asset. operations << client.operation.mutate do |m| m.asset_group_asset_operation = client.operation.create_resource.asset_group_asset do |aga| aga.field_type = :HOTEL_PROPERTY aga.asset_group = client.path.asset_group(customer_id, ASSET_GROUP_TEMPORARY_ID) aga.asset = hotel_property_asset_resource_name end end
Perl
This example is not yet available in Perl; you can take a look at the other languages.