Przejście z Content API for Shopping na Merchant API

Z tego przewodnika dowiesz się, jak przeprowadzić migrację z Content API for Shopping do Merchant API w celu zarządzania firmowymi bazami danych.

Za pomocą tego przewodnika możesz przeprowadzić migrację dotychczasowej implementacji Content API for Shopping do Merchant API. Więcej informacji o szczegółach Merchant API i jego podrzędnych interfejsach API znajdziesz w artykule Projekt Merchant API.

Rozpocznij

Aby zacząć korzystać z Merchant API, zmień adresy URL żądań na ten format:

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

Aby korzystać z Merchant API, musisz połączyć konto Merchant Center i projekt w chmurze Google Cloud za pomocą metody rejestracji dewelopera:

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

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

Więcej informacji znajdziesz w krótkim przewodniku i dokumentacji Merchant API reference.

Ulepszenia w porównaniu z Content API for Shopping

Merchant API umożliwia automatyzację i usprawnienie procesów w Merchant Center oraz oferuje ulepszone możliwości w porównaniu z Content API for Shopping.

Główne przypadki użycia:

  • Automatyczne zarządzanie kontem
  • Automatyczne zarządzanie produktami
  • Automatyczne zarządzanie asortymentem
  • Raportowanie niestandardowe

Główne obszary do poprawy:

Co się zmieniło:

  • Maksymalna wartość pageSize wzrosła z 250 do 1000 wierszy na wywołanie interfejsu API.
  • Usunięto opóźnienie występujące w przypadku wstawiania produktów, promocji, opinii o produktach i opinii o sprzedawcach po DataSources utworzeniu usunięto.
  • Wprowadzono zaktualizowaną definicję clickPotentialRank w tabeli productView w podrzędnym interfejsie Reporting API:
    • Ranking produktów na podstawie clickPotential jest normalizowany do wartości od 1 do 1000.
  • AccountIdAlias w zasobie AccountRelationship umożliwia lepsze zarządzanie złożonymi strukturami kont. Na przykład platformy handlowe używają aliasu zdefiniowanego przez użytkownika zamiast wewnętrznego identyfikatora sprzedawcy, np. identyfikatora konta.

Obsługa gRPC

Merchant API obsługuje gRPC i REST. Możesz jednocześnie używać gRPC w przypadku Merchant API i REST w przypadku Content API for Shopping.

Biblioteki klienta Merchant API wymagają gRPC.

Więcej informacji znajdziesz w artykule Omówienie gRPC.

Zgodność

Ten przewodnik opisuje ogólne zmiany, które dotyczą całego Merchant API.

Merchant API jest zaprojektowany tak, aby współpracować z dotychczasowymi funkcjami Content API for Shopping.

Możesz na przykład używać Merchant Inventories API razem z dotychczasową implementacją Content API for Shopping w wersji 2.1 products. Możesz użyć Content API for Shopping, aby przesłać nowy produkt dostępny lokalnie (który sprzedajesz w sklepie stacjonarnym), a następnie użyć zasobu LocalInventory w Merchant Inventories API, aby zarządzać informacjami o tym produkcie w sklepie.

Ulepszenia w porównaniu z Content API

Merchant API jest lepszy od Content API w tych obszarach:

Przyjrzyj się tym zmianom bardziej szczegółowo.

Obsługa wersji i podrzędne interfejsy API

Merchant API wprowadza koncepcje wersjonowania i podrzędnych interfejsów API. Modułowa konstrukcja ułatwia korzystanie z interfejsu, ponieważ pozwala skupić się na potrzebnych podrzędnych interfejsach API i ułatwia przyszłe migracje do nowszych wersji. Wersjonowanie będzie stosowane w adresach URL żądań. Strategia jest podobna do tej w interfejsie Google Ads API.

Bardziej niezawodne żądania

Adresy URL żądań do Merchant API wymagają więcej parametrów do wywoływania Merchant API. Obejmuje to zasób, wersję, nazwę (identyfikatory) i metodę (niestandardowe metody). Więcej informacji znajdziesz w artykule Identyfikatory kont i produktów oraz przykłady.

Zasady AIP dotyczące identyfikatorów

Content API for Shopping używa identyfikatorów do identyfikowania zasobów (np. merchantId, productId), a Merchant API używa name identyfikatora, aby zachować zgodność z AIP (patrz Zasady ulepszania interfejsu API).

Identyfikator {name} zawiera identyfikator zasobu i jego element nadrzędny (lub potencjalnie wiele elementów nadrzędnych), tak że {name} jest równy accounts/{account}/products/{product}.

Wszystkie wywołania odczytu i zapisu zwracają pole name jako identyfikator zasobu.

{name} zawiera też identyfikatory kolekcji accounts/ i products/.

Merchant API używa {account} do odwoływania się do identyfikatora w Merchant Center i {product} do odwoływania się do identyfikatorów produktów.

Na przykład zaimplementuj metodę getName(), aby pobrać name z zasobu, i zapisz wynik jako zmienną zamiast samodzielnie tworzyć name na podstawie identyfikatorów sprzedawcy i zasobu.

Oto przykład użycia pola name w wywołaniach:

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

Tabela pokazuje, jak zmienia się żądanie products.get w Content API for Shopping:

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}

Więcej informacji znajdziesz w artykule Zmiany identyfikatorów.

Inny przykład: pobieranie produktu z identyfikatorem en~US~1234 z identyfikatora w Merchant Center 4321 za pomocą Merchant API wyglądałoby tak:

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

gdzie {name} jest równe accounts/4321/products/en~US~1234. To nowe pole name jest zwracane jako identyfikator zasobu we wszystkich wywołaniach odczytu i zapisu w Merchant API.

W Content API for Shopping dwukropek (:) oznacza separator w nazwie produktu, a w Merchant API tę funkcję pełni tylda (~). Identyfikator Merchant API nie zawiera części channel.

Na przykład identyfikator produktu w Content API for Shopping:

channel:contentLanguage:feedLabel:offerId.

w Merchant API wygląda tak:

contentLanguage~feedLabel~offerId.

Pola nadrzędne dla zasobów podrzędnych

W Merchant API wszystkie zasoby podrzędne mają parent pole. Za pomocą pola parent możesz określić {name} zasobu, do którego chcesz wstawić element podrzędny, zamiast przekazywać cały zasób nadrzędny. Możesz też użyć pola parent z list

Aby na przykład wyświetlić listę asortymentu lokalnego dla danego produktu, określ produktu name w polu parent metody list. W tym przypadku dany product jest parent zasobów LocalInventory zwróconych.

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

Aby pobrać cały asortyment lokalny dla produktu en~US~1234' i konta 4321 żądanie wyglądałoby tak:

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

Element nadrzędny to accounts/{account}/products/{product}. Pamiętaj, że w tym przypadku zasób localInventories ma 2 elementy nadrzędne uwzględnione w identyfikatorze name (accounts/ i products/), ponieważ konto jest elementem nadrzędnym zasobu produktu.

Typowe wyliczenia

Używanie typowych wyliczeń zapewnia większą spójność.

Pole Destination.DestinationEnum określa powierzchnie, na których mają się wyświetlać Twoje zasoby. DestinationEnum zawiera listę wszystkich dostępnych wartości kierowania na miejsca docelowe i jest ujednolicony w podrzędnych interfejsach API, np. w przypadku atrybutów promocji.

Pole ReportingContext.ReportingContextEnum reprezentuje kontekst, którego dotyczą problemy z kontem i produktem. To pole jest używane w metodach raportowania (np. w przypadku IssueSeverityPerReportingContext).

Zgodność wsteczna

Gdy zaczniesz korzystać z Merchant API, dotychczasowa integracja z Content API for Shopping będzie nadal działać bez zakłóceń. Więcej informacji znajdziesz w artykule Zgodność.

Po przeprowadzeniu migracji podrzędnych interfejsów API do Merchant API zalecamy używanie tylko Merchant API w przypadku tych interfejsów.

Dostępność zdalnego wywołania procedury (gRPC)

gRPC to nowy zalecany sposób integracji z Merchant API.

Jego zalety to:

Niestandardowe grupowanie staje się wbudowanym grupowaniem

Grupowanie działa wydajniej, gdy używasz wywołań asynchronicznych. Dowiedz się więcej o używaniu wywołań równoległych do grupowania w Merchant API oraz o tym, jak refaktoryzować kod na potrzeby jednoczesnych żądań.

Aby przyspieszyć migrację, zalecamy korzystanie z klient bibliotek.

Merchant API nie obsługuje metody customBatch dostępnej w Content API for Shopping. Zamiast tego przeczytaj artykuł Wysyłanie kilku żądań jednocześnie lub wykonywanie wywołań asynchronicznie.

.

Ten przykład w języku Java pokazuje, jak wstawić dane wejściowe produktu:

   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);
  }
}

Jeśli używasz customBatch w Content API i potrzebujesz tej funkcji w Merchant API, napisz w opinii, dlaczego.

Wyjątkowe funkcje

Przyszłe funkcje będą dostępne tylko w Merchant API. (Będzie kilka wyjątków, np. specyfikacja rocznego pliku danych na 2025 r).

Funkcje dostępne tylko w Merchant API:

  • Reviews API. Używaj opinii, aby wdrażać oceny produktów i sklepów oraz nimi zarządzać. Więcej informacji znajdziesz w artykułach Opinie o sprzedawcach i Opinie o produktach.
  • Powiadomienia: zarejestruj się, aby otrzymywać powiadomienia push o zmianach danych produktów na koncie.

Cena

Oto co się zmieniło w przypadku Price w pakiecie Merchant Common:

Content API for Shopping Merchant API
Pole kwoty value:string amountMicros:int64
Pole waluty currency:string currencyCode:string

Kwota Price jest teraz zapisywana w mikrach, gdzie 1 milion mikrów odpowiada standardowej jednostce waluty.

W Content API for Shopping Price była liczbą dziesiętną w postaci ciągu znaków.

Nazwa pola kwoty zmieniła się z value na amountMicros.

Nazwa pola waluty zmieniła się z currency na currencyCode. Format nadal jest zgodny z ISO 4217.

Najnowsze aktualizacje i ogłoszenia

Bardziej szczegółowe informacje znajdziesz w informacjach o wersji dotyczących poszczególnych podrzędnych interfejsów API. Aby otrzymywać regularne zbiorcze informacje o Merchant API, zapoznaj się z naszymi najnowszymi aktualizacjami.

Więcej szczegółowych informacji i dodatkowe informacje o Merchant API znajdziesz na stronie dla deweloperów oraz w ogólnym przewodniku migracji .

Szczegółowe informacje o Merchant API i jego podrzędnych interfejsach API znajdziesz w artykule Projekt Merchant API.