Ta sekcja zawiera informacje o sposobie wysyłania do Google ograniczonych czasowo aktualizacji elementów asortymentu. Interfejs Incremental Update API umożliwia przekazywanie aktualizacji i usuwanie elementów z zasobów reklamowych piaskownicy lub środowiska produkcyjnego w czasie zbliżonym do rzeczywistego.
Ta funkcja jest przeznaczona przede wszystkim w przypadku aktualizacji, których nie możesz przewidzieć, takich jak zamknięcia awaryjne. Z reguły wszelkie zmiany przesyłane za pomocą interfejsu Przyrostowej aktualizacji API powinny zostać wprowadzone w ciągu godziny. Jeśli zmiana nie musi zostać odzwierciedlona od razu, możesz użyć przetwarzania zbiorczego. Aktualizacje przyrostowe są przetwarzane nie dłużej niż 5 minut.
Wymagania wstępne
Przed wdrożeniem aktualizacji przyrostowych musisz wykonać te czynności:
- Zostanie utworzone konto usługi z rolą Edytujący w projekcie w Actions. Więcej informacji znajdziesz w artykule Tworzenie i konfigurowanie projektu.
- Pliki danych w środowisku produkcyjnym lub piaskownicy są hostowane i pozyskiwane. Więcej informacji znajdziesz w artykule Pozyskiwanie wsadowe.
- (Opcjonalne, ale zalecane) Zainstaluj bibliotekę klienta Google w wybranym języku, aby ułatwić korzystanie z protokołu OAuth 2.0 podczas wywoływania interfejsu API. Przykładowe fragmenty kodu znajdujące się poniżej korzystają z tych bibliotek. W przeciwnym razie konieczna będzie ręczna obsługa wymiany tokenów zgodnie z opisem w artykule Uzyskiwanie dostępu do interfejsów API Google za pomocą OAuth 2.0.
Punkty końcowe
W poniższych prośbach zastąp te elementy:
- PROJECT_ID: identyfikator projektu Google Cloud powiązany z projektem utworzonym w sekcji Tworzenie i konfigurowanie projektu.
- TYPE: typ elementu (właściwość
@type
) obiektu w pliku danych, który chcesz zaktualizować. - ENTITY_ID (usuń tylko punkt końcowy): identyfikator elementu do usunięcia. Pamiętaj, aby w adresie URL zakodować identyfikator jednostki.
- DELETE_TIME (tylko usunięcie punktu końcowego): pole opcjonalne na oznaczenie czasu usunięcia elementu w Twoich systemach (domyślnie jest to pole w momencie odebrania żądania). Wartość czasu nie może przypadać w przyszłości. Gdy wysyłasz encję za pomocą wywołania przyrostowego, obsługa wersji encji też używa pola
delete_time
w przypadku wywołania usuwania. Sformatuj tę wartość jakoyyyy-mm-ddTHH:mm:ssZ
Zaktualizowanie punktu końcowego
Aby zmodyfikować encję, wyślij żądanie HTTP POST do poniższego punktu końcowego i dołącz ładunek z aktualizacjami i dodatkami. W jednym wywołaniu interfejsu API możesz zaktualizować maksymalnie 1000 elementów.
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities:batchPush
Jeśli na przykład chcesz zaktualizować encje w projekcie o identyfikatorze „delivery-provider-id”, punkt końcowy będzie wyglądał tak:
https://actions.googleapis.com/v2/apps/delivery-provider-id/entities:batchpush
Usuń punkt końcowy
Aby usunąć encję z zasobów reklamowych, wyślij żądanie HTTP DELETE do poniższego punktu końcowego.
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities/TYPE/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME
Aby na przykład usunąć encję „MenuSection” o identyfikatorze „menuSection_122” z projektu „delivery-provider-id”, należy wykonać wywołanie HTTP DELETE API w celu:
https://actions.googleapis.com/v2/apps/delivery-provider-id/entities/MenuSection/menuSection_122?entity.vertical=FOODORDERING
Środowisko piaskownicy
Aby używać interfejsu Przyrostowej aktualizacji API w zasobach reklamowych w piaskownicy, postępuj zgodnie ze wskazówkami w sekcji Punkty końcowe powyżej, ale wysyłaj żądania do /v2/sandbox/apps/
zamiast do /v2/apps/
.
https://actions.googleapis.com/v2/sandbox/apps/PROJECT_ID/entities:batchPush
https://actions.googleapis.com/v2/sandbox/apps/PROJECT_ID/entities/TYPE/ENTITY_ID?entity.vertical=FOODORDERING&delete_time=DELETE_TIME
Aktualizuję elementy
Każde żądanie POST musi zawierać parametry żądania wraz z ładunkiem JSON zawierającym uporządkowane dane dowolnego typu encji wymienionego w schemacie zasobów.
Zaktualizuj ładunek
Plik JSON powinien wyglądać tak samo jak w pliku danych wsadowym, z tymi różnicami:
- Rozmiar treści ładunku nie powinien przekraczać 5 MB. Podobnie jak w przypadku plików danych wsadowych zalecamy usuwanie odstępów, aby można było dopasować więcej danych.
- Oto jak wygląda koperta:
{ "requests": [ { "entity": { "data":"ENTITY_DATA", "name": "apps/project_id>/entities/type/entity_id" }, "update_time":"UPDATE_TIMESTAMP" }, ], "vertical": "FOODORDERING" }
W powyższym ładunku zastąp to:
- ENTITY_DATA: encja w formacie JSON zserializowana jako ciąg znaków. Encja JSON-LD musi zostać przekazana jako ciąg znaków w polu
data
. - UPDATE_TIMESTAMP (opcjonalnie): sygnatura czasowa aktualizacji elementu w Twoich systemach. Wartość czasu nie może przypadać w przyszłości. Domyślna sygnatura czasowa to moment otrzymania żądania przez Google. Gdy wysyłasz encję za pomocą żądania przyrostowego, obsługa wersji encji też używa pola
update_time
w przypadku żądania dodania/aktualizacji.
Przykłady
Przykład 1. Aktualizowanie informacji o restauracji
Załóżmy, że musisz pilnie zaktualizować numer telefonu do restauracji. Twoja aktualizacja zawiera plik JSON dla całej restauracji.
Przyjrzyjmy się zbiorczemu plikowi danych podobnemu do tego:
{ "@type": "Restaurant", "@id": "restaurant12345", "name": "Some Restaurant", "url": "https://www.provider.com/somerestaurant", "telephone": "+16501234567", "streetAddress": "345 Spear St", "addressLocality": "San Francisco", "addressRegion": "CA", "postalCode": "94105", "addressCountry": "US", "latitude": 37.472842, "longitude": -122.217144 }
Przyrostowa aktualizacja za pomocą metody POST w protokole HTTP będzie wyglądać tak:
POST v2/sandbox/apps/provider-project/entities:batchPush Host: actions.googleapis.com Content-Type: application/ld+json { "requests": [ { "entity": { "name": "apps/provider-project/entities/restaurant/restaurant12345", "data": { "@type": "Restaurant", "@id": "restaurant12345", "name": "Some Restaurant", "url": "https://www.provider.com/somerestaurant", "telephone": "+16501235555", "streetAddress": "345 Spear St", "addressLocality": "San Francisco", "addressRegion": "CA", "postalCode": "94105", "addressCountry": "US", "latitude": 37.472842, "longitude": -122.217144 } } } "vertical": "FOODORDERING" }
Przykład 2. Aktualizowanie wielu restauracji
Aby zaktualizować 2 elementy restauracji w jednym wywołaniu interfejsu API, żądanie HTTP POST będzie wyglądać tak:
POST v2/sandbox/apps/provider-project/entities:batchPush Host: actions.googleapis.com Content-Type: application/ld+json { "requests": [ { "entity": { "name": "apps/provider-project/entities/restaurant/restaurant12345", "data": { "@type": "Restaurant", "@id": "restaurant12345", "name": "Some Restaurant", "url": "https://www.provider.com/somerestaurant", "telephone": "+16501235555", "streetAddress": "345 Spear St", "addressLocality": "San Francisco", "addressRegion": "CA", "postalCode": "94105", "addressCountry": "US", "latitude": 37.472842, "longitude": -122.217144 } } }, { "entity": { "name": "apps/provider-project/entities/restaurant/restaurant123", "data": { "@type": "Restaurant", "@id": "restaurant123", "name": "Some Other Restaurant", "url": "https://www.provider.com/somerestaurant", "telephone": "+16501231235", "streetAddress": "385 Spear St", "addressLocality": "San Mateo", "addressRegion": "CA", "postalCode": "94115", "addressCountry": "US" } } } ] "vertical": "FOODORDERING" }
Przykład 3. Aktualizowanie ceny pozycji w menu
Załóżmy, że chcesz zmienić cenę pozycji w menu. Tak jak w przykładzie 1, aktualizacja musi zawierać plik JSON dotyczący całego elementu najwyższego poziomu (menu), a plik danych korzysta ze schematu zasobów reklamowych w wersji 1.
Przyjrzyjmy się zbiorczemu plikowi danych podobnemu do tego:
{ "@type": "MenuItemOffer", "@id": "menuitemoffer6680262", "sku": "offer-cola", "menuItemId": "menuitem896532", "price": 3.00, "priceCurrency": "USD" }
Przyrostowa aktualizacja metodą POST będzie wtedy wyglądała następująco:
POST v2/sandbox/apps/provider-project/entities:batchPush Host: actions.googleapis.com Content-Type: application/ld+json { "requests": [ { "entity": { "name": "apps/provider-project/entities/menuitemoffer/menuitemoffer6680262", "data": { "@type": "MenuItemOffer", "@id": "menuitemoffer6680262", "sku": "offer-cola", "menuItemId": "menuitem896532", "price": 1.00, "priceCurrency": "USD" }, "vertical": "FOODORDERING" } } ] "vertical": "FOODORDERING" }
Dodawanie encji
Jeśli chcesz dodawać elementy, unikaj aktualizacji zasobów reklamowych. Zamiast tego skorzystaj z procesu przesyłania zbiorczych plików danych zgodnie ze schematem zasobów reklamowych w wersji 2.
Usuwanie elementu
Aby usunąć encje najwyższego poziomu, użyj nieco zmodyfikowanego punktu końcowego i w żądaniu użyj HTTP DELETE zamiast HTTP POST.
Usuwanie elementu najwyższego poziomu
Rozważ sytuację, w której chcesz usunąć restaurację z pliku danych. Musisz też usunąć jej usługi i menu.
Przykładowy punkt końcowy elementu menu o identyfikatorze „provider/restauracja/menu/nr”:
DELETE v2/apps/delivery-provider-id/entities/menu/provider%2Frestaurant%2Fmenu%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
Przykładowy punkt końcowy elementu restauracji o identyfikatorze „https://www.provider.com/Restaurant/nr”:
DELETE v2/apps/delivery-provider-id/entities/restaurant/provider%2Frestaurant%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
Przykładowy punkt końcowy dla encji usługi o identyfikatorze „https://www.provider.com/Restaurant/service/nr”:
DELETE v2/apps/delivery-provider-id/entities/service/provider%2Frestaurant%2Fservice%2Fnr?entity.vertical=FOODORDERING
Host: actions.googleapis.com
}
Usuwanie podrzędnych elementów
Nie używaj metody HTTP DELETE do usuwania elementu podrzędnego w jednostce najwyższego poziomu, np. pozycji menu w menu. Usunięcie podrzędnych elementów należy traktować jako aktualizację elementu najwyższego poziomu, w której element podrzędny został usunięty z odpowiedniej listy lub elementu reverseReference.
Kody odpowiedzi interfejsu API
Pomyślne wywołanie nie oznacza, że plik danych jest prawidłowy ani prawidłowy, tylko że zostało wykonane wywołanie interfejsu API. Pomyślne wywołania otrzymują kod odpowiedzi HTTP 200 i pustą treść odpowiedzi:
{}
W przypadku niepowodzenia kod odpowiedzi HTTP będzie inny niż 200, a jej treść będzie zawierać informacje o tym, co poszło nie tak.
Jeśli na przykład użytkownik ustawił w kopercie wartość „pionowa” na FAKE_VERTICAL
, otrzymasz taki komunikat:
{
"error": {
"code": 400,
"message": "Invalid value at 'entity.vertical' (TYPE_ENUM), \"FAKE_VERTICAL\"",
"status": "INVALID_ARGUMENT",
"details": [
{
"@type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "entity.vertical",
"description": "Invalid value at 'entity.vertical' (TYPE_ENUM), \"FAKE_VERTICAL\""
}
]
}
]
}
}
Przykładowy kod
Poniżej znajdziesz kilka przykładów wykorzystania interfejsu Incremental Update API w różnych językach. Te przykłady korzystają z Google Auth Libraries i zakładają, że plik danych korzysta ze schematu zasobów reklamowych w wersji 1. Alternatywne rozwiązania znajdziesz w artykule o używaniu OAuth 2.0 w aplikacjach międzyserwerowych.
Aktualizuję elementy
Node.js
Ten kod korzysta z biblioteki uwierzytelniania Google dla środowiska Node.js.
const {auth} = require('google-auth-library') const request = require('request'); // The service account client secret file downloaded from the Google Cloud Console const serviceAccountJson = require('./service-account.json') // entity.json is a file that contains the entity data in json format const entity = require('./entity.json') const ENTITY_ID = 'your/entity/id' const PROJECT_ID = 'type/your-project-id' /** * Get the authorization token using a service account. */ async function getAuthToken() { let client = auth.fromJSON(serviceAccountJson) client.scopes = ['https://www.googleapis.com/auth/assistant'] const tokens = await client.authorize() return tokens.access_token; } /** * Send an incremental update to update or add an entity */ async function updateEntity(entity) { const token = await getAuthToken() request.post({ headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, url: `https://actions.googleapis.com/v2/apps/${PROJECT_ID}/entities:batchPush`, body: { requests: [ { entity: { data: JSON.stringify(entity) name: `apps/${PROJECT_ID}/entities/${ENTITY_ID}` } } ], vertical: 'FOODORDERING' }, json: true }, (err, res, body) => { if (err) { return console.log(err); } console.log(`Response: ${JSON.stringify(res)}`) }) } updateEntity(entity)
Python
Ten kod korzysta z biblioteki uwierzytelniania Google na potrzeby Pythona.
from google.oauth2 import service_account from google.auth.transport.requests import AuthorizedSession import json import urllib PROJECT_ID = 'your-project-id' ENTITY_ID = 'type/your/entity/id' ENDPOINT = 'https://actions.googleapis.com/v2/apps/%s/entities:batchPush' % ( PROJECT_ID) # service-account.json is the service account client secret file downloaded from the # Google Cloud Console credentials = service_account.Credentials.from_service_account_file( 'service-account.json') scoped_credentials = credentials.with_scopes( ['https://www.googleapis.com/auth/assistant']) authed_session = AuthorizedSession(scoped_credentials) # Retrieving the entity update_file = open("entity.json") #JSON file containing entity data in json format. data = update_file.read() entity = {} entity['data'] = data #entity JSON-LD serialized as string entity['name'] = 'apps/%s/entities/%s' % (PROJECT_ID, urllib.quote(ENTITY_ID, '') ) # Populating the request request = {} request['entity'] = entity requestArray = [request] # Populating the payload payload = {} payload['requests'] = requestArray payload['vertical'] = 'FOODORDERING' response = authed_session.post(ENDPOINT, json=payload) print(response.text) #if successful, will be '{}'
Java
Ten kod korzysta z biblioteki uwierzytelniania Google na potrzeby Javy.
private static final String PROJECT_ID = "your-project-id"; private static final String ENTITY_ID = "type/your-entity-id"; /** * Get the authorization token using a service account. */ private static String getAuthToken() { InputStream serviceAccountFile = Example.class.getClassLoader().getResourceAsStream("service-account.json"); ServiceAccountCredentials.Builder credentialsSimpleBuilder = ServiceAccountCredentials.fromStream(serviceAccountFile).toBuilder(); credentialsSimpleBuilder.setScopes(ImmutableList.of("https://www.googleapis.com/auth/assistant")); AccessToken accessToken = credentialsSimpleBuilder.build().refreshAccessToken(); return accessToken.getTokenValue(); } /** * Send an incremental update to update or add an entity. * @param entityId The id of the entity to update. * @param entity the json of the entity to be updated. */ public void updateEntity(String entityId, JSONObject data) { String authToken = getAuthToken(); String endpoint = String.format("https://actions.googleapis.com/v2/apps/%s/entities/:batchPush", PROJECT_ID); JSONObject entity = new JSONObject(); entity.put("data", data.toString()); entity.put("name", String.format("apps/%s/entities/%s", PROJECT_ID, URLEncoder.encode(ENTITY_ID, "UTF-8"))); JSONObject request = new JSONObject(); request.put("entity", entity); JSONArray requestArray = new JSONArray(); requestArray.put(request); JSONObject payload = new JSONObject(); payload.put("requests", requestArray); payload.put("vertical", FOODORDERING); // Execute POST request executePostRequest(endpoint, authToken, payload); }
Usuwanie elementów
Node.js
Ten kod korzysta z biblioteki uwierzytelniania Google dla środowiska Node.js.
const {auth} = require('google-auth-library') const request = require('request'); // The service account client secret file downloaded from the Google Cloud Console const serviceAccountJson = require('./service-account.json') // entity.json is a file that contains the entity data in json format const entity = require('./entity.json') const ENTITY_ID = 'restaurant/http://www.provider.com/somerestaurant' const PROJECT_ID = 'your-project-id' /** * Get the authorization token using a service account. */ async function getAuthToken() { let client = auth.fromJSON(serviceAccountJson) client.scopes = ['https://www.googleapis.com/auth/assistant'] const tokens = await client.authorize() return tokens.access_token; } /** * Send an incremental update to delete an entity */ async function deleteEntity(entityId) { const token = await getAuthToken() request.delete({ headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, url: `https://actions.googleapis.com/v2/apps/${PROJECT_ID}/entities/${encodeURIComponent(entityId)}?entity.vertical=FOODORDERING`, body: {}, json: true }, (err, res, body) => { if (err) { return console.log(err); } console.log(`Response: ${JSON.stringify(res)}`) }) } deleteEntity(ENTITY_ID)
Python
Ten kod korzysta z biblioteki uwierzytelniania Google na potrzeby Pythona.
from google.oauth2 import service_account from google.auth.transport.requests import AuthorizedSession import json import urllib # Service config PROJECT_ID = 'your-project-id' ENTITY_ID = 'restaurant/http://www.provider.com/somerestaurant' DELETE_TIME = '2018-04-07T14:30:00-07:00' ENDPOINT = 'https://actions.googleapis.com/v2/apps/%s/entities/%s?entity.vertical=FOODORDERING&delete_time=%s' % ( PROJECT_ID, urllib.quote(ENTITY_ID, ''), urllib.quote(DELETE_TIME, '')) # service-account.json is the service account client secret file downloaded from the # Google Cloud Console credentials = service_account.Credentials.from_service_account_file( 'service-account.json') scoped_credentials = credentials.with_scopes( ['https://www.googleapis.com/auth/assistant']) authed_session = AuthorizedSession(scoped_credentials) response = authed_session.delete(ENDPOINT) print(response.text) #if successful, will be '{}'
Java
Ten kod korzysta z biblioteki uwierzytelniania Google na potrzeby Javy.
private static final String PROJECT_ID = "your-project-id"; private static final String ENTITY_ID = "restaurant/http://www.provider.com/somerestaurant"; /** * Get the authorization token using a service account. */ private static String getAuthToken() { InputStream serviceAccountFile = Example.class.getClassLoader().getResourceAsStream("service-account.json"); ServiceAccountCredentials.Builder credentialsSimpleBuilder = ServiceAccountCredentials.fromStream(serviceAccountFile).toBuilder(); credentialsSimpleBuilder.setScopes(ImmutableList.of("https://www.googleapis.com/auth/assistant")); AccessToken accessToken = credentialsSimpleBuilder.build().refreshAccessToken(); return accessToken.getTokenValue(); } /** * Send an incremental update to delete an entity. * @param entityId The id of the entity to delete. */ public void deleteEntity(String entityId) { String authToken = getAuthToken(); String endpoint = String.format( "https://actions.googleapis.com/v2/apps/%s/entities/%s?entity.vertical=FOODORDERING", PROJECT_ID, URLEncoder.encode(entityId, "UTF-8")); // Execute DELETE request System.out.println(executeDeleteRequest(endpoint, authToken)); }
Przypadki użycia
W poniższych przypadkach użycia znajdują się przykłady aktualizacji przyrostowych, pełnych aktualizacji pliku danych i treści na wysokim poziomie w wywołaniu interfejsu API:
Scenariusz | Element do zaktualizowania | Opis i efekty |
---|---|---|
Wyłączanie usługi | Service |
Usługę musisz wyłączyć z nieprzewidzianych powodów. Aktualizacje przyrostowe: zaktualizuj odpowiedni element Pełne pliki danych: pamiętaj, aby przed kolejnym pobraniem przez Google zaktualizować element z pełnych plików danych, tak aby parametr |
Konkretny produkt jest niedostępny | MenuItemOffer |
Aktualizacje przyrostowe: Wyślij encję jądrową MenuItemOffer z wartością inventoryLevel ustawioną na 0 dla danego MenuItem , a wszystkie pozostałe dane bez zmian. |
Zmiana ceny elementu menu | MenuItemOffer |
Aktualizacje przyrostowe: Wyślij encję jądrową MenuItemOffer z price ustawioną na zaktualizowaną cenę danego MenuItem , a wszystkie pozostałe dane bez zmian. |
Dodaj nowy element najwyższego poziomu Dotyczy tylko encji typów |
Menu , Restaurant , Service |
Możesz na przykład dodać nowe menu do restauracji. Pełne pliki danych: dodaj encję do plików danych i poczekaj na przetwarzanie zbiorcze. |
Trwale usuń element najwyższego poziomu Dotyczy tylko encji typów |
Menu , Restaurant , Service |
Aktualizacje przyrostowe: prześlij jednorazowe usunięcie. Pełne pliki danych: pamiętaj, aby usunąć element z pełnych plików danych przed kolejnym pobraniem przez Google. W przeciwnym razie zostanie on ponownie dodany. |
Dodaj nowy obszar dostawy na wybranym koncie (Service ) |
ServiceArea |
Dodatkowe pliki danych: wyślij problematyczny element ServiceArea z niezmienionymi wszystkimi polami, tak jak w przypadku pełnych plików danych, z nowym obszarem dostawy określonym w parametrach polygon , geoRadius lub postalCode . |
Zaktualizuj szacowany czas dostawy w: Service |
ServiceHours |
Przyrostowe pliki danych: wysyłaj ServiceHours w taki sam sposób jak w plikach danych, z wyjątkiem tego, że jego parametr leadTimeMin jest odpowiednio aktualizowany. |
Zaktualizuj ceny dostawy w: Service |
Fee |
Dodatkowe pliki danych: prześlij pełne pliki danych Fee z zaktualizowanym plikiem price . |
Zaktualizuj godziny dostawy lub na wynos w: Service |
ServiceHours |
Przyrostowe pliki danych: wysyłaj ServiceHours tak samo jak w plikach danych, ale jego właściwości opens i closes są odpowiednio aktualizowane. |
Service (zmień minimalną kwotę zamówienia) |
Fee |
Przyrostowe pliki danych: wysyłaj pełne pliki Fee z aktualizacją minPrice |
Trwale usuń MenuItem |
Menu |
Przyrostowe pliki danych: wysyłaj MenuItem tak samo jak w plikach danych, ale z wartością parentMenuSectionId pustą.
|
Docelowy poziom usług w zakresie czasu przetwarzania zadań wsadowych i aktualizacji przyrostowych
Encja zaktualizowana lub usunięta przy użyciu wsadu zostanie przetworzona w ciągu 2 godzin w trybie najlepszych wyników, a encja zaktualizowana za pomocą aktualizacji przyrostowej zostanie przetworzona w ciągu 5 minut. Nieaktualny element jest usuwany za 7 dni.
Możesz wysłać do Google:
- wiele zadań wsadowych dziennie, aby zapewnić aktualność zasobów reklamowych; LUB
- Jedno zadanie wsadowe dziennie i przyrostowe interfejsy API, aby zapewnić aktualność asortymentu.