Insert promotions asynchronously
Stay organized with collections
Save and categorize content based on your preferences.
Merchant API code sample to insert promotions asynchronously.
Java
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package shopping.merchant.samples.promotions.v1;
import com.google.api.core.ApiFuture;
import com.google.api.core.ApiFutureCallback;
import com.google.api.core.ApiFutures;
import com.google.api.gax.core.FixedCredentialsProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.protobuf.Timestamp;
import com.google.shopping.merchant.promotions.v1.Attributes;
import com.google.shopping.merchant.promotions.v1.CouponValueType;
import com.google.shopping.merchant.promotions.v1.InsertPromotionRequest;
import com.google.shopping.merchant.promotions.v1.OfferType;
import com.google.shopping.merchant.promotions.v1.ProductApplicability;
import com.google.shopping.merchant.promotions.v1.Promotion;
import com.google.shopping.merchant.promotions.v1.PromotionsServiceClient;
import com.google.shopping.merchant.promotions.v1.PromotionsServiceSettings;
import com.google.shopping.merchant.promotions.v1.RedemptionChannel;
import com.google.shopping.type.CustomAttribute;
import com.google.shopping.type.Destination.DestinationEnum;
import com.google.type.Interval;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import shopping.merchant.samples.utils.Authenticator;
import shopping.merchant.samples.utils.Config;
/** This class demonstrates how to insert multiple promotions asynchronously. */
public class InsertPromotionsAsyncSample {
private static String generateRandomString() {
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuilder sb = new StringBuilder(8);
for (int i = 0; i < 8; i++) {
sb.append(characters.charAt(random.nextInt(characters.length())));
}
return sb.toString();
}
private static Promotion createPromotion(String accountId) {
String merchantPromotionId = generateRandomString();
Attributes attributes =
Attributes.newBuilder()
.setProductApplicability(ProductApplicability.ALL_PRODUCTS)
.setOfferType(OfferType.GENERIC_CODE)
.setGenericRedemptionCode("ABCD1234")
.setLongTitle("My promotion")
.setCouponValueType(CouponValueType.PERCENT_OFF)
.addPromotionDestinations(DestinationEnum.SHOPPING_ADS)
.setPercentOff(10)
// Note that promotions have a 6-month limit.
// For more information, read here: https://support.google.com/merchants/answer/2906014
// Also note that only promotions valid within the past 365 days are shown in the UI.
.setPromotionEffectiveTimePeriod(
Interval.newBuilder()
.setStartTime(Timestamp.newBuilder().setSeconds(1726842472))
.setEndTime(Timestamp.newBuilder().setSeconds(1726842473))
.build())
.build();
return Promotion.newBuilder()
.setName(String.format("accounts/%s/merchantPromotions/%s", accountId, merchantPromotionId))
.setPromotionId(merchantPromotionId)
.setContentLanguage("fr")
.setTargetCountry("CH")
.addRedemptionChannel(RedemptionChannel.ONLINE)
.setAttributes(attributes)
// Custom attributes allow you to add additional information which is not available in
// Attributes. For example, you might want to pilot experimental functionality.
.addCustomAttributes(
CustomAttribute.newBuilder()
.setName("another example name")
.setValue("another example value")
.build())
.build();
}
public static void asyncInsertPromotions(String accountId, String dataSourceId) throws Exception {
GoogleCredentials credential = new Authenticator().authenticate();
PromotionsServiceSettings merchantPromotionsServiceSettings =
PromotionsServiceSettings.newBuilder()
.setCredentialsProvider(FixedCredentialsProvider.create(credential))
.build();
try (PromotionsServiceClient merchantPromotionsServiceClient =
PromotionsServiceClient.create(merchantPromotionsServiceSettings)) {
// Arbitrarily creates five merchant promotions with random IDs.
List<InsertPromotionRequest> requests = new ArrayList<>();
for (int i = 0; i < 5; i++) {
InsertPromotionRequest request =
InsertPromotionRequest.newBuilder()
.setParent(String.format("accounts/%s", accountId))
.setPromotion(createPromotion(accountId))
.setDataSource(String.format("accounts/%s/dataSources/%s", accountId, dataSourceId))
.build();
requests.add(request);
}
// Inserts the merchant promotions.
List<ApiFuture<Promotion>> futures =
requests.stream()
.map(
request ->
merchantPromotionsServiceClient.insertPromotionCallable().futureCall(request))
.collect(Collectors.toList());
// Creates callback to handle the responses when all are ready.
ApiFuture<List<Promotion>> responses = ApiFutures.allAsList(futures);
ApiFutures.addCallback(
responses,
new ApiFutureCallback<List<Promotion>>() {
@Override
public void onSuccess(List<Promotion> results) {
System.out.println("Inserted merchant promotions below:");
System.out.println(results);
}
@Override
public void onFailure(Throwable throwable) {
System.out.println(throwable);
}
},
MoreExecutors.directExecutor());
} catch (Exception e) {
System.out.println(e);
}
}
public static void main(String[] args) throws Exception {
Config config = Config.load();
asyncInsertPromotions(config.getAccountId().toString(), "<YOUR_DATA_SOURCE_ID>");
}
}
Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.
Last updated 2025-08-13 UTC.
[null,null,["Last updated 2025-08-13 UTC."],[[["\u003cp\u003eThis code sample demonstrates how to insert multiple promotions asynchronously using the Merchant API in Java.\u003c/p\u003e\n"],["\u003cp\u003eThe \u003ccode\u003eInsertPromotionsAsyncSample\u003c/code\u003e class showcases the process of creating and inserting promotions, including setting attributes like product applicability, offer type, and redemption details.\u003c/p\u003e\n"],["\u003cp\u003eThe code uses \u003ccode\u003eApiFuture\u003c/code\u003e and \u003ccode\u003eApiFutures\u003c/code\u003e to manage asynchronous requests for inserting multiple promotions, improving efficiency.\u003c/p\u003e\n"],["\u003cp\u003eThe sample provides a \u003ccode\u003ecreatePromotion\u003c/code\u003e method to build promotion objects with random IDs and a defined set of attributes, including setting a time limit.\u003c/p\u003e\n"],["\u003cp\u003eA callback function is used to handle the responses for asynchronous actions, providing a way to process the successful insertion of promotions or handle failures.\u003c/p\u003e\n"]]],["The code asynchronously inserts multiple promotions into a merchant account. It generates five `InsertPromotionRequest` objects, each containing promotion details like merchant ID, product applicability, offer type, and redemption code. Each request is sent using `PromotionsServiceClient`, and responses are handled via callbacks. On success, it prints the inserted promotions; on failure, it logs the error. It uses `ApiFutures` to manage multiple requests concurrently.\n"],null,["# Insert promotions asynchronously\n\nMerchant API code sample to insert promotions asynchronously. \n\n### Java\n\n\n // Copyright 2023 Google LLC\n //\n // Licensed under the Apache License, Version 2.0 (the \"License\");\n // you may not use this file except in compliance with the License.\n // You may obtain a copy of the License at\n //\n // https://www.apache.org/licenses/LICENSE-2.0\n //\n // Unless required by applicable law or agreed to in writing, software\n // distributed under the License is distributed on an \"AS IS\" BASIS,\n // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n // See the License for the specific language governing permissions and\n // limitations under the License.\n\n package shopping.merchant.samples.promotions.v1;\n import com.google.api.core.ApiFuture;\n import com.google.api.core.ApiFutureCallback;\n import com.google.api.core.ApiFutures;\n import com.google.api.gax.core.FixedCredentialsProvider;\n import com.google.auth.oauth2.GoogleCredentials;\n import com.google.common.util.concurrent.MoreExecutors;\n import com.google.protobuf.Timestamp;\n import com.google.shopping.merchant.promotions.v1.Attributes;\n import com.google.shopping.merchant.promotions.v1.CouponValueType;\n import com.google.shopping.merchant.promotions.v1.InsertPromotionRequest;\n import com.google.shopping.merchant.promotions.v1.OfferType;\n import com.google.shopping.merchant.promotions.v1.ProductApplicability;\n import com.google.shopping.merchant.promotions.v1.Promotion;\n import com.google.shopping.merchant.promotions.v1.PromotionsServiceClient;\n import com.google.shopping.merchant.promotions.v1.PromotionsServiceSettings;\n import com.google.shopping.merchant.promotions.v1.RedemptionChannel;\n import com.google.shopping.type.CustomAttribute;\n import com.google.shopping.type.Destination.DestinationEnum;\n import com.google.type.Interval;\n import java.util.ArrayList;\n import java.util.List;\n import java.util.Random;\n import java.util.stream.Collectors;\n import shopping.merchant.samples.utils.Authenticator;\n import shopping.merchant.samples.utils.Config;\n\n /** This class demonstrates how to insert multiple promotions asynchronously. */\n public class InsertPromotionsAsyncSample {\n\n private static String generateRandomString() {\n String characters = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\";\n Random random = new Random();\n StringBuilder sb = new StringBuilder(8);\n for (int i = 0; i \u003c 8; i++) {\n sb.append(characters.charAt(random.nextInt(characters.length())));\n }\n return sb.toString();\n }\n\n private static Promotion createPromotion(String accountId) {\n String merchantPromotionId = generateRandomString();\n\n Attributes attributes =\n Attributes.newBuilder()\n .setProductApplicability(ProductApplicability.ALL_PRODUCTS)\n .setOfferType(OfferType.GENERIC_CODE)\n .setGenericRedemptionCode(\"ABCD1234\")\n .setLongTitle(\"My promotion\")\n .setCouponValueType(CouponValueType.PERCENT_OFF)\n .addPromotionDestinations(DestinationEnum.SHOPPING_ADS)\n .setPercentOff(10)\n // Note that promotions have a 6-month limit.\n // For more information, read here: https://support.google.com/merchants/answer/2906014\n // Also note that only promotions valid within the past 365 days are shown in the UI.\n .setPromotionEffectiveTimePeriod(\n Interval.newBuilder()\n .setStartTime(Timestamp.newBuilder().setSeconds(1726842472))\n .setEndTime(Timestamp.newBuilder().setSeconds(1726842473))\n .build())\n .build();\n\n return Promotion.newBuilder()\n .setName(String.format(\"accounts/%s/merchantPromotions/%s\", accountId, merchantPromotionId))\n .setPromotionId(merchantPromotionId)\n .setContentLanguage(\"fr\")\n .setTargetCountry(\"CH\")\n .addRedemptionChannel(RedemptionChannel.ONLINE)\n .setAttributes(attributes)\n // Custom attributes allow you to add additional information which is not available in\n // Attributes. For example, you might want to pilot experimental functionality.\n .addCustomAttributes(\n CustomAttribute.newBuilder()\n .setName(\"another example name\")\n .setValue(\"another example value\")\n .build())\n .build();\n }\n\n public static void asyncInsertPromotions(String accountId, String dataSourceId) throws Exception {\n GoogleCredentials credential = new Authenticator().authenticate();\n\n PromotionsServiceSettings merchantPromotionsServiceSettings =\n PromotionsServiceSettings.newBuilder()\n .setCredentialsProvider(FixedCredentialsProvider.create(credential))\n .build();\n\n try (PromotionsServiceClient merchantPromotionsServiceClient =\n PromotionsServiceClient.create(merchantPromotionsServiceSettings)) {\n\n // Arbitrarily creates five merchant promotions with random IDs.\n List\u003cInsertPromotionRequest\u003e requests = new ArrayList\u003c\u003e();\n for (int i = 0; i \u003c 5; i++) {\n InsertPromotionRequest request =\n InsertPromotionRequest.newBuilder()\n .setParent(String.format(\"accounts/%s\", accountId))\n .setPromotion(createPromotion(accountId))\n .setDataSource(String.format(\"accounts/%s/dataSources/%s\", accountId, dataSourceId))\n .build();\n requests.add(request);\n }\n\n // Inserts the merchant promotions.\n List\u003cApiFuture\u003cPromotion\u003e\u003e futures =\n requests.stream()\n .map(\n request -\u003e\n merchantPromotionsServiceClient.insertPromotionCallable().futureCall(request))\n .collect(Collectors.toList());\n\n // Creates callback to handle the responses when all are ready.\n ApiFuture\u003cList\u003cPromotion\u003e\u003e responses = ApiFutures.allAsList(futures);\n ApiFutures.addCallback(\n responses,\n new ApiFutureCallback\u003cList\u003cPromotion\u003e\u003e() {\n @Override\n public void onSuccess(List\u003cPromotion\u003e results) {\n System.out.println(\"Inserted merchant promotions below:\");\n System.out.println(results);\n }\n\n @Override\n public void onFailure(Throwable throwable) {\n System.out.println(throwable);\n }\n },\n MoreExecutors.directExecutor());\n } catch (Exception e) {\n System.out.println(e);\n }\n }\n\n\n public static void main(String[] args) throws Exception {\n Config config = Config.load();\n asyncInsertPromotions(config.getAccountId().toString(), \"\u003cYOUR_DATA_SOURCE_ID\u003e\");\n }\n } \n https://github.com/google/merchant-api-samples/blob/c6de994268c785ce22af0065932518a9ac5b3c03/java/src/main/java/shopping/merchant/samples/promotions/v1/InsertPromotionsAsyncSample.java"]]