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를 사용하려면 다음과 같이 개발자 등록 방법을 사용하여 판매자 센터 계정과 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를 사용하면 판매자 센터에서 워크플로를 자동화하고 간소화할 수 있으며 Content API for Shopping보다 향상된 기능을 제공합니다.

주요 사용 사례:

  • 자동 계정 관리
  • 자동 제품 관리
  • 자동 인벤토리 관리
  • 맞춤 보고서

주요 개선 영역:

변경사항

  • 최대 pageSize가 API 호출당 250개 행에서 1,000개 행으로 증가했습니다.
  • 제품 삽입, 프로모션, 제품 리뷰 및 판매자 리뷰에 존재했던 지연이 DataSources 생성 후 수정되었습니다.
  • Reporting 하위 API의 table under the 에 있는 clickPotentialRank의 업데이트된 정의 출시:
      productView
    • 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 기능과 함께 작동하도록 설계되었습니다.

예를 들어 기존 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를 호출하기 위한 매개변수가 더 많이 필요합니다. 여기에는 리소스, 버전, 이름 (식별자), 메서드 (비표준 메서드)가 포함됩니다. 자세한 내용은 계정 및 제품 식별자를 참고하세요.

식별자를 위한 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}를 사용하여 판매자 센터 ID를 참조하고 {product}를 사용하여 제품 식별자를 참조합니다.

예를 들어 getName() 메서드를 구현하여 리소스에서 name을 가져오고 판매자 및 리소스 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를 사용하여 판매자 센터 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}을 지정할 수 있습니다. `parent` 필드를 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/)에 포함된 두 개의 상위 요소가 있습니다.

일반적인 enum

일반적인 enum을 사용하면 일관성이 향상됩니다.

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에 이 기능이 필요한 경우 의견에서 그 이유를 알려주세요.

독점적인 기능

향후 기능은 Merchant API에만 표시됩니다. (2025년 연간 피드 사양과 같은 몇 가지 예외가 있습니다 .)

Merchant API 전용 기능은 다음과 같습니다.

  • 리뷰 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 설계를 참고하세요.