Z tej sekcji dowiesz się, jak wysyłać do Google uaktualnienia zasobów reklamowych, które mają znaczenie czasowe. Interfejs API Incremental Update umożliwia przesyłanie aktualizacji i usuwanie elementów w piaskownicy lub w asortymencie produkcyjnym w czasie zbliżonym do rzeczywistego.
Ta funkcja jest przeznaczona głównie do aktualizacji, których nie można przewidzieć, takich jak zamknięcia awaryjne. Zmiana przesłana za pomocą interfejsu Incremental Update API powinna być zmianą, która musi zostać opublikowana w ciągu maksymalnie 1 godziny. Jeśli zmiana nie musi być wprowadzona natychmiast, możesz użyć przetworzenia zbiorczego. Aktualizacje przyrostowe są przetwarzane w ciągu nie dłużej niż 5 minut.
Wymagania wstępne
Przed wdrożeniem aktualizacji przyrostowych musisz wykonać te czynności:
- Tworzy konto usługi z przypisaną rolą Edytujący w Twoim projekcie Asystenta. Więcej informacji znajdziesz w artykule Tworzenie i konfigurowanie projektu.
- Pliki danych produkcyjne lub z piaskownicy są hostowane i przetwarzane. Więcej informacji znajdziesz w artykule Przetwarzanie zbiorcze.
- (Opcjonalnie, ale zalecane) Zainstaluj bibliotekę klienta Google w wybranym języku, aby ułatwić korzystanie z OAuth 2.0 podczas wywoływania interfejsu API. Poniżej znajdziesz przykłady kodu, które korzystają z tych bibliotek. W przeciwnym razie musisz ręcznie przeprowadzić wymianę tokenów zgodnie z opisem w artykule Uzyskiwanie dostępu do interfejsów API Google za pomocą protokołu OAuth 2.0.
Punkty końcowe
W poniższych żądaniach zastąp:
- PROJECT_ID: identyfikator projektu Google Cloud powiązany z projektem utworzonym w sekcji Tworzenie i konfigurowanie projektu.
- TYPE: typ encji (właściwość
@type
) obiektu w pliku danych, który chcesz zaktualizować. - ENTITY_ID (tylko punkt końcowy usuwania): identyfikator jednostki do usunięcia. Zakoduj identyfikator za pomocą kodowania URL.
- DELETE_TIME (tylko punkt końcowy usuwania): opcjonalne pole do oznaczania czasu, w którym element został usunięty z Twoich systemów (domyślnie jest to czas otrzymania żądania). Wartość czasu nie może być w przyszłości. Podczas wysyłania elementu za pomocą wywołania cząstkowego wersja elementu używa również pola
delete_time
w przypadku wywołania usuwania. Sformatuj tę wartość jakoyyyy-mm-ddTHH:mm:ssZ
Zaktualizowanie punktu końcowego
Aby zmodyfikować element, wyślij żądanie HTTP POST do tego punktu końcowego i dołącz ładunek aktualizacji i dodatków. W ramach jednego wywołania interfejsu API możesz zaktualizować maksymalnie 1000 elementów.
https://actions.googleapis.com/v2/apps/PROJECT_ID/entities:batchPush
Jeśli np. chcesz zaktualizować elementy 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ąć element z zasobow, wyślij żądanie HTTP DELETE do podanego niżej 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ąć z projektu „delivery-provider-id” element „MenuSection” o identyfikatorze „menuSection_122”, musisz wykonać wywołanie interfejsu API DELETE HTTP do:
https://actions.googleapis.com/v2/apps/delivery-provider-id/entities/MenuSection/menuSection_122?entity.vertical=FOODORDERING
Piaskownica
Aby korzystać z interfejsu Incremental Update API w sandboxie, postępuj zgodnie ze wskazówkami podanymi powyżej w sekcji Punkty końcowe, ale wysyłaj żądania do punktu końcowego /v2/sandbox/apps/
zamiast /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 elementu wymienionego w schemacie zasobów reklamowych.
Aktualizacja ładunku
Plik JSON powinien wyglądać tak samo jak plik danych zbiorczych, z tymi różnicami:
- Rozmiar ładunku nie powinien przekraczać 5 MB. Podobnie jak w przypadku plików danych zbiorczych, zalecamy usunięcie spacji, aby zmieścić więcej danych.
- Korespondencja ma postać:
{ "requests": [ { "entity": { "data":"ENTITY_DATA", "name": "apps/project_id>/entities/type/entity_id" }, "update_time":"UPDATE_TIMESTAMP" }, ], "vertical": "FOODORDERING" }
W powyższym pliku danych zastąp:
- ENTITY_DATA: element w formacie JSON serializowany jako ciąg znaków. Encję JSON-LD należy przekazać jako ciąg znaków w polu
data
. - UPDATE_TIMESTAMP (opcjonalnie): sygnatura czasowa, kiedy element został zaktualizowany w Twoich systemach. Wartość czasu nie może być w przyszłości. Domyślna sygnatura czasowa to moment, w którym Google otrzymało żądanie. Podczas wysyłania elementu za pomocą żądania przyrostowego wersja elementu korzysta z pola
update_time
w przypadku żądania dodania lub zaktualizowania.
Przykłady
Przykład 1. Aktualizowanie restauracji
Załóżmy, że musisz pilnie zaktualizować numer telefonu restauracji. Aktualizacja zawiera plik JSON całej restauracji.
Weź pod uwagę plik danych zbiorczego, który wygląda tak:
{ "@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 }
Wtedy przyrostowa aktualizacja za pomocą 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 } } } "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 menu
Załóżmy, że musisz zmienić cenę pozycji menu. Podobnie jak w przykładzie 1, Twoja aktualizacja musi zawierać dane JSON dotyczące całego elementu najwyższego poziomu (menu), a plik danych musi używać schematu zasobów reklamowych w wersji 1.
Weź pod uwagę plik danych zbiorczego, który wygląda tak:
{ "@type": "MenuItemOffer", "@id": "menuitemoffer6680262", "sku": "offer-cola", "menuItemId": "menuitem896532", "price": 3.00, "priceCurrency": "USD" }
Wtedy przyrostowa aktualizacja za pomocą żądania 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/menuitemoffer/menuitemoffer6680262", "data": { "@type": "MenuItemOffer", "@id": "menuitemoffer6680262", "sku": "offer-cola", "menuItemId": "menuitem896532", "price": 1.00, "priceCurrency": "USD" }, "vertical": "FOODORDERING" } } ] "vertical": "FOODORDERING" }
Dodawanie elementu
Aby dodawać elementy, nie używaj aktualizacji asortymentu. Zamiast tego użyj procesu przesyłania plików zbiorczych zgodnie z opisem w sekcji Schemat asortymentu w wersji 2.
Usuwanie elementu
Aby usunąć elementy najwyższego poziomu, użyj nieco zmodyfikowanego punktu końcowego i w żądaniu użyj metody HTTP DELETE zamiast HTTP POST.
Usuwanie encji najwyższego poziomu
Wyobraź sobie sytuację, w której chcesz usunąć restaurację z pliku danych. Musisz też usunąć usługi i menu.
Przykład punktu końcowego dla elementu menu o identyfikatorze „provider/restaurant/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 dla obiektu 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ład punktu końcowego dla elementu 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 podelementów
Nie używaj metody HTTP DELETE do usuwania podelementu w elemencie najwyższego poziomu, np. pozycji menu w menu. Zamiast tego usuwanie podelementów należy traktować jako aktualizację elementu najwyższego poziomu, w którym podelement jest usuwany z odpowiedniej listy lub reverseReference.
Kody odpowiedzi interfejsu API
Pomyślne wywołanie nie oznacza, że plik danych jest prawidłowy lub poprawny, tylko że zostało wykonane wywołanie interfejsu API. Pomyślne wywołania otrzymują kod odpowiedzi HTTP 200 oraz pustą treść odpowiedzi:
{}
W przypadku niepowodzenia kod odpowiedzi HTTP nie będzie miał wartości 200, a ciało odpowiedzi będzie wskazywać, co poszło nie tak.
Jeśli np. użytkownik ustawi wartość „vertical” w kopercie na
FAKE_VERTICAL
, otrzymasz tę wiadomość:
{
"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 użycia interfejsu Incremental Update API w różnych językach. Te przykłady korzystają z bibliotek Google Auth Library i zakładają, że plik danych używa schematu asortymentu w wersji 1. Alternatywnych rozwiązań szukaj w artykule Używanie protokołu OAuth 2.0 w aplikacjach międzyserwerowych.
Aktualizuję elementy
Node.js
Ten kod używa biblioteki Google do uwierzytelniania w 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 dla 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 Google do uwierzytelniania w Javie.
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 używa biblioteki Google do uwierzytelniania w 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 dla 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 Google do uwierzytelniania w Javie.
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
Poniższe przypadki użycia to przykłady przyrostowych aktualizacji, pełnych aktualizacji pliku danych oraz treści na wysokim poziomie w wywołaniu interfejsu API:
Scenariusz | Element do zaktualizowania | Opis i efekty |
---|---|---|
Wyłączanie usługi | Service |
musisz wyłączyć usługę z nieprzewidzianego powodu; Aktualizacje przyrostowe: zaktualizuj obiekt Pełne pliki danych: przed następnym pobraniem przez Google pamiętaj, aby zaktualizować element z pełnych plików danych, aby wartość |
konkretny produkt jest niedostępny, | MenuItemOffer |
Aktualizacje przyrostowe: wyślij element MenuItemOffer , w którym element inventoryLevel ma wartość 0 dla danego MenuItem , a wszystkie inne dane pozostają bez zmian. |
Zmiana ceny pozycji menu | MenuItemOffer |
Aktualizacje przyrostowe: prześlij element MenuItemOffer zawierający price zaktualizowaną ceną dla danego MenuItem , a wszystkie inne dane bez zmian. |
Dodawanie nowej jednostki najwyższego poziomu Dotyczy tylko elementów typu |
Menu , Restaurant , Service |
Możesz na przykład dodać nowe menu do restauracji. Pełne pliki danych: dodaj element w plikach danych i poczekaj na przetworzenie zbiorczego. |
Trwałe usuwanie elementu najwyższego poziomu Dotyczy tylko elementów typu |
Menu , Restaurant , Service |
Aktualizacje przyrostowe: wyślij wyraźne usunięcie. Pełne pliki danych: przed kolejnym pobraniem przez Google pamiętaj, aby usunąć element z pełnych plików danych. W przeciwnym razie zostanie on ponownie dodany. |
Dodawanie nowej strefy dostawy w określonym Service |
ServiceArea |
Pliki danych przyrostowych: prześlij odpowiednią jednostkę ServiceArea ze wszystkimi polami, tak jak w przypadku pełnych plików danych, z nową strefą dostawy określoną w polu polygon , geoRadius lub postalCode . |
Zaktualizuj szacowany czas dostawy w Service |
ServiceHours |
Dodatkowe pliki danych: wyślij ServiceHours w taki sam sposób jak w plikach danych, z tą różnicą, że leadTimeMin zostanie odpowiednio zaktualizowany. |
Zaktualizuj ceny dostawy w Service |
Fee |
Pliki danych przyrostowe: prześlij pełny plik danych Fee z zaktualizowanymi wartościami w kolumnie price . |
Zmień godziny dostawy lub odbioru na wynos w Service |
ServiceHours |
Dodatkowe pliki danych: wyślij ServiceHours tak samo jak w plikach danych, z tą różnicą, że właściwości opens i closes zostaną odpowiednio zaktualizowane. |
Service (zmiana minimalnej wartości zamówienia) |
Fee |
Pliki danych przyrostowe: prześlij pełny plik danych Fee z aktualizacją minPrice |
Trwałe usuwanie MenuItem |
Menu |
Dodatkowe pliki danych: wyślij MenuItem tak samo jak w plikach danych, ale z pustym parentMenuSectionId .
|
Docelowy poziom usług dotyczący czasu przetwarzania zadań zbiorczych i aktualizacji przyrostowych
Obiekt zaktualizowany lub usunięty w ramach partii zostanie przetworzony w ciągu 2 godzin w trybie dołożymy wszelkich starań, a obiekt zaktualizowany w ramach aktualizacji przyrostowej – w ciągu 5 minut. Nieaktualne elementy są usuwane po 7 dniach.
Możesz wysłać do Google:
- wiele zadań zbiorczych dziennie, aby aktualizować asortyment, lub
- Jedno zadanie zbiorcze dziennie i interfejsy API w celu aktualizowania asortymentu.