Content API for Shopping から Merchant API に移行する

このガイドでは、ビジネスデータ管理のための Content API for Shopping から Merchant API への移行プロセスについて説明します。

このガイドを使用して、既存の Content API for Shopping の実装を Merchant API に移行できます。Merchant API とそのサブ API の詳細については、Merchant API の設計をご覧ください。

始める

Merchant API の使用を開始するには、リクエスト URL を次の形式に変更します。

https://merchantapi.googleapis.com/{SUB_API}/{VERSION}/{RESOURCE_NAME}:{METHOD}

Merchant API を使用するには、デベロッパー登録の方法を使用して、Merchant Center アカウントと Google Cloud プロジェクトをリンクする必要があります。

POST https://merchantapi.googleapis.com/accounts/v1/accounts/{ACCOUNT_ID}/developerRegistration:registerGcp

{
  developer_email:"example-email@example.com"
}

詳しくは、クイックスタート ガイドと Merchant API リファレンスをご覧ください。

Content API for Shopping からの改善点

Merchant API を使用すると、Merchant Center でワークフローを自動化して効率化できます。また、Content API for Shopping よりも機能が強化されています。

主なユースケース

  • アカウント管理の自動化
  • 商品管理の自動化
  • 在庫管理の自動化
  • カスタム レポートの作成

主な改善点

変更点

  • 最大 pageSize が API 呼び出しあたり 250 行から 1,000 行に増加しました。
  • 商品挿入、プロモーション、商品レビュー、および 販売者レビューで DataSources作成後に 発生していた遅延が修正されました。
  • Reporting サブ API の table under the productView テーブルでclickPotentialRankの更新された定義がリリースされました。
    • clickPotential に基づく商品のランキングが、1 ~ 1,000 の値に正規化されます。
  • AccountIdAlias リソースの AccountRelationship を使用すると、複雑なアカウント構造をより適切に管理できます。たとえば、マーケットプレイスでは、アカウント ID など、販売者の内部 ID の代わりにユーザー定義のエイリアスを使用します。

gRPC のサポート

Merchant API は gRPC と REST をサポートしています。Merchant API には gRPC を、Content API for Shopping には REST を同時に使用できます。

Merchant API クライアント ライブラリ には gRPC が必要です。

詳しくは、 gRPC の概要をご覧ください。

互換性

このガイドでは、Merchant API 全体に適用される一般的な変更について説明します。

Merchant API は、既存の Content API for Shopping の機能と連携するように設計されています。

たとえば、Merchant Inventories API を既存の Content API for Shopping v2.1 products 実装と併用できます。Content API for Shopping を使用して新しいローカル商品(実店舗で販売している商品)をアップロードし、Merchant Inventories API の LocalInventory リソースを使用して、その商品の店舗内情報を管理できます。

Content API からの改善点

Merchant API は、次の点で Content API を改善しています。

これらの変更について詳しく見ていきましょう。

バージョニングとサブ API

Merchant API では、 バージョニングサブ APIの概念が導入されています。モジュール型の設計により、必要なサブ API に集中できるため、使いやすさが向上しています。また、将来の新しいバージョンへの移行も容易になります。バージョニングはリクエスト URL に適用されます。戦略は Google Ads API のエクスペリエンスに似ています。

より堅牢なリクエスト

Merchant API の URL リクエストでは、Merchant API を呼び出すために多くのパラメータが必要です。これには、リソース、バージョン、名前(識別子)、メソッド(標準以外のメソッド)が含まれます。詳しくは、アカウントと商品 識別子をご覧ください。

識別子の AIP 原則

Content API for Shopping では ID を使用してリソースを識別しますが( merchantIdproductId など)、Merchant API では AIP に沿って name 識別子を使用します( API 改善の原則をご覧ください)。

{name} 識別子には、リソース識別子とその親(または複数の親)が含まれます。{name}accounts/{account}/products/{product} と同じです。

すべての読み取り呼び出しと書き込み呼び出しは、リソース識別子として name フィールドを返します。

{name} には、コレクション識別子 accounts/products/ も含まれます。

Merchant API では、{account} は Merchant Center ID を指し、{product} は商品識別子を指します。

name

たとえば、getName() メソッドを実装してリソースから name を取得し、販売者 ID とリソース ID から name を自分で作成するのではなく、出力を変数として保存します。

呼び出しで name フィールドを使用する方法の例を次に示します。

   POST https://merchantapi.googleapis.com/inventories/v1/{PARENT}/regionalInventories:insert

次の表に、Content API for Shopping の products.get リクエストの変更点を示します。

Content API for Shopping Merchant API
GET https://shoppingcontent.googleapis.com/content/v2.1/{merchantId}/products/{productId} GET https://merchantapi.googleapis.com/products/v1/{name}

詳しくは、識別子 の変更をご覧ください。

別の例として、Merchant API を使用して Merchant Center ID 4321 から識別子 en~US~1234 の商品を取得する場合、次のようになります。

    GET
    https://merchantapi.googleapis.com/products/v1/accounts/4321/products/online~en~US~1234

ここで、{name}accounts/4321/products/en~US~1234 と同じです。この新しい名前フィールドは、Merchant API のすべての読み取り呼び出しと書き込み呼び出しのリソース識別子として返されます。

Content API for Shopping では、コロン(:)は商品名の区切り文字を表しますが、Merchant API ではチルダ(~)がこの役割を果たします。Merchant API 識別子には channel 部分が含まれていません。

たとえば、Content API for Shopping の商品 ID は次のようになります。

channel:contentLanguage:feedLabel:offerId

Merchant API では次のようになります。

contentLanguage~feedLabel~offerId

子リソースの親フィールド

Merchant API では、すべての子リソースに parent フィールドがあります。parent フィールドを使用すると、親リソース全体を渡すのではなく、子を挿入するリソースの {name} を指定できます。 フィールドは list でも使用できます。parent

たとえば、特定の商品についてローカル在庫を一覧表示するには、商品の nameparent フィールドに list メソッドを指定します。この場合、指定された product は、返される LocalInventory リソースの parent です。

    GET
    https://merchantapi.googleapis.com/inventories/v1/{parent}/localInventories

商品 en~US~1234' とアカウント 4321 のすべてのローカル在庫を取得する場合、リクエストは次のようになります。

    GET
    https://merchantapi.googleapis.com/inventories/v1/accounts/4321/products/online~en~US~1234/localInventories</code>

親は accounts/{account}/products/{product} です。この場合、アカウントは商品リソースの親であるため、 localInventories リソースには名前識別子(accounts/products/)に含まれる 2 つの親があります。

共通の列挙型

共通の列挙型を使用すると、一貫性が向上します。

Destination.DestinationEnum フィールドは、リソースを表示するサーフェスを指定します。 DestinationEnum には、配信先ターゲティングに使用できるすべての値が一覧表示され、 プロモーション 属性など、サブ API 全体で統一されています。

ReportingContext.ReportingContextEnum フィールドは、アカウントと商品の問題が適用されるコンテキストを表します。 このフィールドは、レポート メソッド( IssueSeverityPerReportingContext など)で使用されます。

下位互換性

Merchant API の使用を開始しても、既存の Content API for Shopping の統合は中断されることなく機能し続けます。詳しくは、 互換性をご覧ください。

サブ API を Merchant API に移行したら、移行したサブ API には Merchant API のみを使用することをおすすめします。

リモート プロシージャ コール(gRPC)の可用性

gRPC は、Merchant API と統合する新しい推奨方法です。

次のような利点があります。

カスタム バッチ処理が組み込みのバッチ処理になる

非同期呼び出しを使用すると、バッチ処理の効率が向上します。Merchant API で並列呼び出しを使用して バッチ処理を実現する方法と、同時リクエスト用にコードをリファクタリング する方法について詳しくは、こちらをご覧ください。

移行を迅速に進めるために、クライアント ライブラリを使用することをおすすめします。

Merchant API は、Content API for Shopping の customBatch メソッドをサポートしていません。代わりに、複数の リクエストを一度に送信するか、呼び出しを 非同期で実行してください。

をご覧ください。

次の Java サンプルは、商品入力を挿入する方法を示しています。

   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.api.gax.grpc.InstantiatingGrpcChannelProvider;
import com.google.auth.oauth2.GoogleCredentials;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.shopping.merchant.products.v1.Availability;
import com.google.shopping.merchant.products.v1.Condition;
import com.google.shopping.merchant.products.v1.InsertProductInputRequest;
import com.google.shopping.merchant.products.v1.ProductAttributes;
import com.google.shopping.merchant.products.v1.ProductInput;
import com.google.shopping.merchant.products.v1.ProductInputsServiceClient;
import com.google.shopping.merchant.products.v1.ProductInputsServiceSettings;
import com.google.shopping.merchant.products.v1.Shipping;
import com.google.shopping.type.Price;
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 a product input */
public class InsertProductInputAsyncSample {

  private static String getParent(String accountId) {
    return String.format("accounts/%s", accountId);
  }

  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 ProductInput createRandomProduct() {
    Price price = Price.newBuilder().setAmountMicros(33_450_000).setCurrencyCode("USD").build();

    Shipping shipping =
        Shipping.newBuilder().setPrice(price).setCountry("GB").setService("1st class post").build();

    Shipping shipping2 =
        Shipping.newBuilder().setPrice(price).setCountry("FR").setService("1st class post").build();

    ProductAttributes attributes =
        ProductAttributes.newBuilder()
            .setTitle("A Tale of Two Cities")
            .setDescription("A classic novel about the French Revolution")
            .setLink("https://exampleWebsite.com/tale-of-two-cities.html")
            .setImageLink("https://exampleWebsite.com/tale-of-two-cities.jpg")
            .setAvailability(Availability.IN_STOCK)
            .setCondition(Condition.NEW)
            .setGoogleProductCategory("Media > Books")
            .addGtins("9780007350896")
            .addShipping(shipping)
            .addShipping(shipping2)
            .build();

    return ProductInput.newBuilder()
        .setContentLanguage("en")
        .setFeedLabel("CH")
        .setOfferId(generateRandomString())
        .setProductAttributes(attributes)
        .build();
  }

  public static void asyncInsertProductInput(Config config, String dataSource) throws Exception {

    // Obtains OAuth token based on the user's configuration.
    GoogleCredentials credential = new Authenticator().authenticate();

    // Creates a channel provider. This provider manages a pool of gRPC channels
    // to enhance throughput for bulk operations. Each individual channel in the pool
    // can handle up to approximately 100 concurrent requests.
    //
    // Channel: A single connection pathway to the service.
    // Pool: A collection of multiple channels managed by this provider.
    //   Requests are distributed across the channels in the pool.
    //
    // We recommend estimating the number of concurrent requests you'll make, divide by 50 (50%
    // utilization of channel capacity), and set the pool size to that number.
    InstantiatingGrpcChannelProvider channelProvider =
        InstantiatingGrpcChannelProvider.newBuilder().setPoolSize(30).build();

    // Creates service settings using the credentials retrieved above.
    ProductInputsServiceSettings productInputsServiceSettings =
        ProductInputsServiceSettings.newBuilder()
            .setCredentialsProvider(FixedCredentialsProvider.create(credential))
            .setTransportChannelProvider(channelProvider)
            .build();

    // Creates parent to identify where to insert the product.
    String parent = getParent(config.getAccountId().toString());

    // Calls the API and catches and prints any network failures/errors.
    try (ProductInputsServiceClient productInputsServiceClient =
        ProductInputsServiceClient.create(productInputsServiceSettings)) {

      // Creates five insert product input requests with random product IDs.
      List<InsertProductInputRequest> requests = new ArrayList<>(5);
      for (int i = 0; i < 5; i++) {
        InsertProductInputRequest request =
            InsertProductInputRequest.newBuilder()
                .setParent(parent)
                // You can only insert products into datasource types of Input "API", and of Type
                // "Primary" or "Supplemental."
                // This field takes the `name` field of the datasource.
                .setDataSource(dataSource)
                // If this product is already owned by another datasource, when re-inserting, the
                // new datasource will take ownership of the product.
                .setProductInput(createRandomProduct())
                .build();

        requests.add(request);
      }

      System.out.println("Sending insert product input requests");
      List<ApiFuture<ProductInput>> futures =
          requests.stream()
              .map(
                  request ->
                      productInputsServiceClient.insertProductInputCallable().futureCall(request))
              .collect(Collectors.toList());

      // Creates callback to handle the responses when all are ready.
      ApiFuture<List<ProductInput>> responses = ApiFutures.allAsList(futures);
      ApiFutures.addCallback(
          responses,
          new ApiFutureCallback<List<ProductInput>>() {
            @Override
            public void onSuccess(List<ProductInput> results) {
              System.out.println("Inserted products 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();
    // Identifies the data source that will own the product input.
    String dataSource = "accounts/" + config.getAccountId() + "/dataSources/{datasourceId}";

    asyncInsertProductInput(config, dataSource);
  }
}

Content API で customBatch を使用していて、Merchant API でこの機能が必要な場合は、 フィードバックでお知らせください。

Google Pixel だけの機能

今後の機能は Merchant API にのみ追加されます(2025 年の年間フィード仕様など、いくつかの 例外があります)。

Merchant API 固有の機能は次のとおりです。

  • Reviews API。レビューを使用して、商品とショップの評価を実装、管理します。詳しくは、販売者 レビュー商品 レビューをご覧ください。
  • 通知: アカウントの商品データの変更に関するプッシュ通知を 受け取るように登録します。

価格

Merchant Common パッケージの Price の変更点は次のとおりです。

Content API for Shopping Merchant API
金額フィールド value:string amountMicros:int64
通貨フィールド currency:string currencyCode:string

Price の金額はマイクロ秒単位で記録されるようになりました。100 万マイクロ秒は通貨の標準単位に相当します。

Content API for Shopping では、Price は文字列形式の 10 進数でした。

金額フィールド名が value から amountMicros に変更されました。

通貨フィールド名が currency から currencyCode に変更されました。形式は引き続きISO 4217です。

最新情報とお知らせ

より詳細な更新情報については、各サブ API に固有のリリースノートをご覧ください。Merchant API の定期的な集約更新については、最新の更新情報をご覧ください。

詳細については、 デベロッパー サイト 概要と移行 ガイドをご覧ください。

Merchant API とそのサブ APIについて詳しくは、Merchant API の設計をご覧ください。