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 よりも高度な機能を利用できます。

主なユースケース

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

主な改善点:

  • 次のような新機能を備えたサブ API:
    • 注文追跡は、ビジネスの注文追跡履歴をサポートし、正確な配送予定をお客様に提供します。また、そのシグナルにより、送料無料とスピード配送の拡張リスティングも可能になります。
    • 問題の解決では、Merchant Center UI で利用できるのと同じ方法で、診断コンテンツとサポート アクションにアクセスできます。
    • Accounts サブ API の新しいリソース。
    • OmnichannelSettings は、無料ローカル リスティング(FLL)やローカル在庫広告(LIA)など、オムニチャネル配信のアカウント構成を管理します。
    • LfpProviders は、在庫データについてローカル フィード パートナー(LFP)プログラムのパートナーに接続します。
    • GbpAccounts ローカル店舗データのために Google ビジネス プロフィール アカウントに接続します。
    • OnlineReturnPolicy を使用すると、オンライン ポリシーの作成、削除、更新を行うことができます。
  • 在庫、商品データ、その他の API の新しいメソッド。以下が含まれます。
    • Products サブ API の新しいメソッド。
    • ProductsUpdate を使用すると、ProductInput に必要なすべてのフィールドを指定しなくても、個々の商品を更新できます。
  • メイン データソースだけでなく、次のような複数のデータソースを作成できます。
  • 商品レビューと販売者レビューのアップロードについて説明します
  • Merchant API を使用すると、アカウント データの変更に関する通知を有効にできます。

変更内容

  • pageSize の最大値が、API 呼び出しあたり 250 行から 1,000 行に増加しました。
  • DataSources の作成後に、商品の挿入、プロモーション、商品レビュー、販売者レビューで発生していた遅延を修正しました。
  • Reporting サブ API の productView テーブルで、clickPotentialRank の定義を更新しました。
    • clickPotential に基づく商品のランキングは、1 ~ 1,000 の値に正規化されます。
  • AccountRelationship リソースの AccountIdAlias を使用すると、複雑なアカウント構造をより適切に管理できます。たとえば、ショッピングモールでは、アカウント 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 機能と連携するように設計されています。

たとえば、既存の Content API for Shopping v2.1 products 実装とともに Merchant Inventories API を使用できます。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 を呼び出すために追加のパラメータが必要です。これには、リソース、バージョン、名前(識別子)、メソッド(非標準メソッド)が含まれます。詳細については、アカウントと商品の ID と例をご覧ください。

識別子に関する AIP の原則

Content API for Shopping では、リソースの識別には ID(merchantId、productId など)が使用されますが、Merchant API では、AIP に準拠するために name 識別子が使用されます(API 改善の原則を参照)。

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

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

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

Merchant API では、{account} を使用して Merchant Center ID を参照し、{product} を使用して商品 ID を参照します。

たとえば、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 から ID en~US~1234 の商品を取得する場合は、次のようになります。

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

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

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} を指定できます。parent フィールドを list とともに使用することもできます。

たとえば、特定の商品に関するローカル在庫を一覧表示するには、list メソッドの parent フィールドに商品の name を指定します。この場合、指定された 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/en~US~1234/localInventories

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

一般的な列挙型

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

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.ChannelPoolSettings;
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()
            .setChannelPoolSettings(ChannelPoolSettings.staticallySized(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 の詳細については、デベロッパー サイトの概要と移行ガイドをご覧ください。

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