建立及上傳搜尋點動態饋給
建立及上傳搜尋點動態饋給時,請按照下列操作說明進行:
- 請按照搜尋點動態饋給所述的規格,建議每次上傳時,使用不重複的 POI 資料檔案名稱。在檔案名稱中加入時間戳記,例如
POI_1633621547.json。 - 每天將動態饋給上傳至本地 POI SFTP 伺服器,進行完整重新整理。
- 如要查看 SFTP 伺服器詳細資料,請前往合作夥伴入口網站的「Configuration」>「Feeds」部分。
- 上傳前,請使用 POI 動態饋給驗證工具驗證 POI 動態饋給。
- 在合作夥伴入口網站的「Ingestion」>「History」部分,查看動態饋給擷取狀態。
檔案封裝規範
為確保成功擷取,請遵守下列封裝規定:
- 單一匯總 JSON 封存檔 (必要):將所有實體記錄合併為單一 JSON 檔案。建議您將檔案壓縮成單一 GZIP 封存檔,然後上傳。
- 反模式警告:請勿在同一個封存檔中,為每個實體使用一個檔案,或依國家/地區分隔多個檔案。系統不支援這種做法,且會導致擷取失敗。
支援多種語言
「搜尋點」動態饋給支援為特定欄位提供本地化內容。下列欄位屬於 Text 類型,且支援本地化:
namedescriptiondisplay_address
如要提供多種語言的內容,您必須在欄位中指定 default_locale,並在 localizations 清單中提供本地化字串。在單一搜尋點項目中,提供實體的所有本地化版本。請勿將單一實體拆分到多個語言 JSON 檔案中。
範例:
"name": {
"localizations": [
{
"locale": "en",
"text": "Tasty Bites Test Restaurant"
},
{
"locale": "es",
"text": "Restaurante de prueba Tasty Bites"
}
],
"default_locale": "en"
}
圖片使用規範
- 格式:必須是 JPEG、PNG 或 WebP。
- 檔案大小上限:每張圖片不得超過 30 MB。
- 尺寸上限:總像素小於 7,500 萬 (寬度 x 高度 < 75,000,000)。
- 網址類型:圖片素材資源的直接路徑 (例如以 .jpg 結尾)。
- 權限:確認代管伺服器允許 Googlebot 或檢索器存取,且沒有 robots.txt 封鎖圖片目錄。
- 安全搜尋:圖片必須符合 Google 的安全搜尋政策。
動態饋給規格
欄位規定
VssPoi
代表單一搜尋點 (POI) 實體,例如飯店或餐廳。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
poi_id | 字串 | 必填 | 必填。由合作夥伴產生,用於識別搜尋點的字串。 |
name | object(Text) | 必填 | 必填。搜尋點名稱。 |
telephone | 字串 | 搜尋點的聯絡電話號碼,包括國家/地區和區碼,例如 +14567891234。 | |
url | 字串 | 搜尋點公開網站的網址。 注意:這項資訊僅用於比對,不會顯示。 | |
location | object(GeoCoordinates) | 必填 | 必填。搜尋點的位置。 |
display_address | object(Text) | 使用者介面上顯示的地址。 | |
images | 物件陣列(Image) | 搜尋點的圖片。 圖片數量上限:5 張。 | |
rating | 數字 | 搜尋點的平均評分。 | |
num_ratings | 數字 | rating 欄位的評分數量。 | |
rating_scale | 數字 | rating 欄位使用的分級量表。如果最高評分為 5,則 rating_scale 為 5。 | |
category | enum(Category) | 必填 | 必填。代表搜尋點的類別。 |
description | object(Text) | 搜尋點的說明。 | |
| oneOf(additional_data) | 必填 | 這個 oneOf 只能設定一個欄位。 |
文字
代表含有本地化內容的文字。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
localizations | 物件陣列(LocalizedString) | 本地化字串。 | |
default_locale | 字串 | 要用作預設語言的語言代碼,必須存在於本地化設定中。 |
LocalizedString
代表本地化字串。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
locale | 字串 | 文字的語言代碼,例如「en」、「en-US」或「sr-Latn」。 | |
text | 字串 | 指定語言代碼的文字。 |
GeoCoordinates
特定位置的地理資訊,包括經緯度和地址。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
latitude | 數字 | [-90, +90] 度 (含)。如果已設定經度,則為必要欄位,否則為選用欄位。 | |
longitude | 數字 | [-180, +180] 度 (含首尾)。如果已設定緯度,則為必要欄位,否則為選用欄位。 | |
| oneOf(addresses) | 必填 | 這個 oneOf 只能設定一個欄位。 |
PostalAddress
地點的郵寄地址。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
country | 字串 | 必填 | 必填。國家/地區,使用 ISO 3166-1 alpha-2 國家/地區代碼,例如「US」。 |
locality | 字串 | 必填 | 必填。所在地/城市,例如「Mountain View」。 |
region | 字串 | 區域/州/省,例如「CA」。只有在區域通常是地址一部分的國家/地區,才需要填寫這個欄位。(選填) | |
postal_code | 字串 | 必填 | 必填。郵遞區號,例如「94043」。 |
street_address | 字串 | 必填 | 必填。街道地址,例如「1600 Amphitheatre Pkwy」。 |
圖片
代表搜尋點 (POI) 的圖片。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
url | 字串 | 圖片的網址。Google 會檢索這個網址代管的媒體。長度上限:2000。 | |
alt_text | object(Text) | 無障礙功能使用的替代文字。 |
HotelData
飯店專屬動態饋給資料。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
hotel_star_class | 數字 | 官方飯店星級評等值。可用於「5 星級飯店」等標籤。這個值必須是介於 0 到 5 之間的整數。如果無法提供或未指定評分,則應使用 0。如果設為 0,使用者就不會在 UI 上看到星級。 | |
brand_ids | 字串陣列 | 可顯示這間飯店的品牌。 如果這個欄位留空,飯店可以顯示在與動態饋給相關聯的任何品牌下方。 |
LocalData
特定商家動態饋給資料。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
business_hours | object(BusinessHours) | 商家的一般營業時間。 | |
price_range | object(PriceRange) | 商家提供的服務價格範圍。 | |
establishment_category | object(Text) | 商家類型。 | |
brand_landing_pages | 物件陣列(BrandLandingPages) | 必填 | 必填。品牌到達網頁。至少須提供一項。 |
BusinessHours
代表這個地點的營業時間範圍。包含 [TimeRange][madden.vss_poi_feed.TimeRange] 執行個體的集合。 範例:週六營業時間為 09:00-12:00 和 13:00-17:00: time_ranges { open_day: SATURDAY open_time: { hours: 9, minutes: 0 } close_day: SATURDAY close_time: { hours: 12, minutes: 0 } } time_rages { open_day: SATURDAY open_time: { hours: 13, minutes: 0 } close_day: SATURDAY close_time: { hours: 17, minutes: 0 } } 範例:週六營業時間為 21:00 至週日 02:00: time_ranges { open_day: SATURDAY open_time: { hours: 21, minutes: 0 } close_day: SUNDAY close_time: { hours: 2, minutes: 0 } }
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
time_ranges | 物件陣列(TimeRange) | 這個搜尋點的營業時間。每個時段代表一週內 POI 的營業時間範圍。 |
TimeRange
代表 POI 的營業時間範圍,從指定的營業日期/時間開始,到指定的營業日期/時間結束。 結束時間必須晚於開始時間,例如當天稍晚或隔天。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
open_day | enum(DayOfWeek) | 日期範圍的開始日期。 | |
open_time | object(TimeOfDay) | 時間範圍的開始時間。 | |
close_day | enum(DayOfWeek) | 日期範圍的結束日期。 | |
close_time | object(TimeOfDay) | 日期範圍的結束時間。 |
TimeOfDay
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
hours | 數字 | 一天中的小時,以 24 小時制表示。必須大於或等於 0,且通常必須小於或等於 23。API 可能會選擇允許「24:00:00」這個值,用於商家營業結束時間等情境。 | |
minutes | 數字 | 一小時中的分鐘。必須大於或等於 0,且小於或等於 59。 | |
seconds | 數字 | 一分鐘內的第幾秒。必須大於或等於 0,且通常必須小於或等於 59。如果 API 允許閏秒,則可能允許值 60。 | |
nanos | 數字 | 秒數的小數部分,以奈秒為單位。必須大於或等於 0,且小於或等於 999,999,999。 |
PriceRange
搜尋點提供的服務價格範圍。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
min_price | object(Money) | 搜尋點提供的服務最低價格。 | |
max_price | object(Money) | 搜尋點提供的服務最高價格。 |
金額
代表金額與其貨幣類型。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
currency_code | 字串 | ISO 4217 定義的三碼貨幣代碼。 | |
units | 數字 | 金額的整數單位。舉例來說,如果 currencyCode 為 "USD",則 1 個單位為 1 美元。 | |
nanos | 數字 | 金額的奈米 (10^-9) 單位數量。這個值必須介於 -999,999,999 和 +999,999,999 (含) 之間。如果 units 為正值,nanos 必須為正值或零。如果 units 為零,nanos 可為正值、零或負值。如果 units 為負值,nanos 就必須為負值或零。例如,$-1.75 美元的表式方式為 units=-1 和 nanos=-750,000,000。 |
BrandLandingPages
單一搜尋點 (POI) 的本地化品牌到達網頁。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
brand_id | 字串 | 必填 | 必填。這項設定適用的品牌。 |
localized_landing_pages | 物件陣列(LocalizedLandingPage) | 本地化到達網頁。 所有本地化到達網頁的網址和語言代碼欄位值不得重複。 | |
default_url | 字串 | 必填 | 必填。如果沒有任何本地化到達網頁符合使用者的語言,系統會使用預設到達網頁網址。 |
LocalizedLandingPage
搜尋點的本地化到達網頁。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
url | 字串 | 到達網頁的網址。 長度上限:2000。 | |
locales | 字串陣列 | 限制只有指定語言偏好設定的使用者才能存取這個頁面。必須包含語言代碼,例如「en」、「en-US」或「sr-Latn」。 |
類別
代表搜尋點的類別。應與下方的 additional_data oneof 欄位一致。
| 名稱 | 說明 |
|---|---|
UNKNOWN_CATEGORY | |
HOTEL | |
LOCAL |
DayOfWeek
代表星期幾。
| 名稱 | 說明 |
|---|---|
DAY_OF_WEEK_UNSPECIFIED | 未指定星期幾。 |
MONDAY | 星期一 |
TUESDAY | 週二 |
WEDNESDAY | 週三 |
THURSDAY | 週四 |
FRIDAY | Friday (週五) |
SATURDAY | Saturday (週六) |
SUNDAY | 星期日 |
additional_data
必填。類別專屬欄位。這個值應與上方的 category 欄位相符。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
hotel_data | object(HotelData) | 與 | 飯店專屬欄位。 |
local_data | object(LocalData) | 與 | 當地專屬欄位。 |
addresses
必填。地點的地址。
| 欄位名稱 | 類型 | 規定 | 說明 |
|---|---|---|---|
address | object(PostalAddress) | 地點的郵寄地址。 |
定義
VssPoiFeed 定義
// Represents a Point of Interest (POI) data feed provided by a partner. export message VssPoiFeed { // The POIs in the feed. repeated VssPoi data = 1; }
VssPoi 定義
// Represents a single Point of Interest (POI) entity e.g. a hotel or // restaurant. export message VssPoi { // Required. A string generated by the partner that identifies a POI. string poi_id = 1; // The entity name, telephone, url and location are used to support // matching partner inventory with entities already present on Google. // Required. The name of the POI. Text name = 2; // The contact telephone number of the POI including its country and // area codes, e.g. +14567891234. string telephone = 3 [(datapol.semantic_type) = ST_PHONE_NUMBER]; // The url of the POI's public website. // Note: This will be used just for matching purposes, not for display. string url = 4; // Required. The location of the POI. GeoCoordinates location = 5; // The address displayed on the UI. Text display_address = 17; // Images of the POI. // Max number of images: 5. repeated Image images = 6; // Average rating for the POI. float rating = 12; // The number of contributing ratings for the `rating` field. int64 num_ratings = 13; // The rating scale used for the `rating` field. If max rating is 5, then // rating_scale is 5. int32 rating_scale = 14; // Represents the category of the POI. // It should match the `additional_data` oneof field below. export enum Category { LOCAL = 4; } // Required. Represents the category of the POI. Category category = 9; // A description of the POI. Text description = 16; // Required. Category specific fields. // It should match the `category` field above. oneof additional_data { // Local specific fields. LocalData local_data = 15; } }
Text 定義
// Represents a text with localizations. message Text { // Represents a localized string. message LocalizedString { // The text's language tag, such as "en", "en-US" or "sr-Latn". string locale = 1; // The text in the specified locale. string text = 2; } // The localized strings. repeated LocalizedString localizations = 1; // The locale to use as the default language it must be present in the // localizations. string default_locale = 2; }
GeoCoordinates 定義
// The Geo data of a location, including latitude, longitude, and address. message GeoCoordinates { option (datapol.msg_semantic_type) = ST_LOCATION; // [-90, +90] degrees (inclusive). // Required if longitude is set, otherwise nice to have. double latitude = 1; // [-180, +180] degrees (inclusive). // Required if latitude is set, otherwise nice to have. double longitude = 2; // Required. Address for a location. oneof addresses { // Postal address of the location. PostalAddress address = 3; } }
PostalAddress 定義
// The postal address for the location. message PostalAddress { option (datapol.msg_semantic_type) = ST_LOCATION; // Required. The country, using ISO 3166-1 alpha-2 country code, e.g. "US". string country = 1; // Required. The locality/city, e.g. "Mountain View". string locality = 2; // The region/state/province, e.g. "CA". This field is only required in // countries where region is commonly a part of the address. (optional) string region = 3; // Required. The postal code, e.g. "94043". string postal_code = 4; // Required. The street address, e.g. "1600 Amphitheatre Pkwy". string street_address = 5; }
圖片定義
// Represents an image of the Point of Interest (POI). export message Image { // The url of the image. Google will crawl the media hosted at this URL. // Max length: 2000. string url = 1; // The alternative text to be used for accessibility. Text alt_text = 2; }
LocalData 定義
// Establishment specific feed data. message LocalData { // The regular business hours of the establishment. BusinessHours business_hours = 1; // Price range of the services offered by the establishment. PriceRange price_range = 2; // The type of establishment. Text establishment_category = 3; // Required. The brand landing pages. At least one must be provided. repeated BrandLandingPages brand_landing_pages = 4; }
BrandLandingPages 定義
// The Localized brand landing pages for a single Point of Interest (POI). message BrandLandingPages { // Required. The brand this configuration applies to. string brand_id = 1 [(datapol.semantic_type) = ST_PARTNER_ID]; // Localized landing page for the Point of Interest (POI). message LocalizedLandingPage { // The url of the landing page. // Max length: 2000. string url = 1; // Restricts this page to users with the specified language preference. // Must contain language tags, such as "en", "en-US" or "sr-Latn". // Empty list means this page is not restricted by language. repeated string locales = 3; // Restricts this page to users from the specified countries. // Must contain ISO 3166-1 alpha-2 country codes, e.g. "US". // Empty list means this page is not restricted by country. // If `is_default_for_country` is true, this field must not be empty. repeated string countries = 4; // Whether this page should be used as the default fallback for users in // `countries` when no entry for that country matches the user's // language preference. bool is_default_for_country = 5; } // The localized landing pages. // The url and locales fields values must be unique across all the localized // landing pages. repeated LocalizedLandingPage localized_landing_pages = 2; // Required. The default landing page url to be used when none of the // localized landing pages matches the user's language. string default_url = 3; }
範例
搜尋點動態饋給
檔案名稱:poi_1707240000.json
{ "data": [ { "poi_id": "test_restaurant_1", "name": { "localizations": [ { "locale": "en", "text": "Tasty Bites Test Restaurant" } ], "default_locale": "en" }, "telephone": "+1234567890", "url": "https://www.tastybitestest.com", "location": { "latitude": 37.422, "longitude": -122.084, "address": { "country": "US", "locality": "Mountain View", "postal_code": "94043", "street_address": "1600 Amphitheatre Pkwy" } }, "display_address": { "localizations": [ { "locale": "en", "text": "1600 Amphitheatre Pkwy, Mountain View, CA 94043" } ], "default_locale": "en" }, "images": [ { "url": "https://www.tastybitestest.com/images/interior.jpg", "alt_text": { "localizations": [ { "locale": "en", "text": "Cozy dining area of Tasty Bites" } ], "default_locale": "en" } } ], "rating": 4.7, "num_ratings": 150, "rating_scale": 5, "category": "LOCAL", "description": { "localizations": [ { "locale": "en", "text": "A mock restaurant for testing the POI feed ingestion." } ], "default_locale": "en" }, "local_data": { "establishment_category": { "localizations": [ { "locale": "en", "text": "Restaurant" } ], "default_locale": "en" }, "price_range": { "min_price": { "currency_code": "USD", "units": 15, "nanos": 0 }, "max_price": { "currency_code": "USD", "units": 45, "nanos": 0 } }, "business_hours": { "time_ranges": [ { "open_day": "MONDAY", "open_time": { "hours": 11, "minutes": 0 }, "close_day": "MONDAY", "close_time": { "hours": 21, "minutes": 0 } }, { "open_day": "TUESDAY", "open_time": { "hours": 11, "minutes": 0 }, "close_day": "TUESDAY", "close_time": { "hours": 21, "minutes": 0 } }, { "open_day": "WEDNESDAY", "open_time": { "hours": 11, "minutes": 0 }, "close_day": "WEDNESDAY", "close_time": { "hours": 21, "minutes": 0 } }, { "open_day": "THURSDAY", "open_time": { "hours": 11, "minutes": 0 }, "close_day": "THURSDAY", "close_time": { "hours": 22, "minutes": 0 } }, { "open_day": "FRIDAY", "open_time": { "hours": 11, "minutes": 0 }, "close_day": "FRIDAY", "close_time": { "hours": 23, "minutes": 0 } }, { "open_day": "SATURDAY", "open_time": { "hours": 10, "minutes": 0 }, "close_day": "SATURDAY", "close_time": { "hours": 23, "minutes": 0 } }, { "open_day": "SUNDAY", "open_time": { "hours": 10, "minutes": 0 }, "close_day": "SUNDAY", "close_time": { "hours": 20, "minutes": 0 } } ] }, "brand_landing_pages": [ { "brand_id": "tasty_bites_brand", "localized_landing_pages": [ { "url": "https://www.tastybitestest.com/en", "locales": ["en-US", "en-GB"] } ], "default_url": "https://www.tastybitestest.com" } ] } } ] }
多語言搜尋點動態饋給
檔案名稱:poi_multilingual.json
{ "data": [ { "poi_id": "test_restaurant_1", "name": { "localizations": [ { "locale": "en", "text": "Tasty Bites Test Restaurant" }, { "locale": "fr", "text": "Restaurant de test Tasty Bites" } ], "default_locale": "en" }, "telephone": "+1234567890", "url": "https://www.tastybitestest.com", "location": { "latitude": 37.422, "longitude": -122.084, "address": { "country": "US", "locality": "Mountain View", "postal_code": "94043", "street_address": "1600 Amphitheatre Pkwy" } }, "display_address": { "localizations": [ { "locale": "en", "text": "1600 Amphitheatre Pkwy, Mountain View, CA 94043" }, { "locale": "fr", "text": "1600 Amphitheatre Pkwy, Mountain View, CA 94043" } ], "default_locale": "en" }, "images": [ { "url": "https://www.tastybitestest.com/images/interior.jpg", "alt_text": { "localizations": [ { "locale": "en", "text": "Cozy dining area of Tasty Bites" }, { "locale": "fr", "text": "Espace salle à manger accueillant de Tasty Bites" } ], "default_locale": "en" } } ], "rating": 4.7, "num_ratings": 150, "rating_scale": 5, "category": "LOCAL", "description": { "localizations": [ { "locale": "en", "text": "A mock restaurant for testing the POI feed ingestion." }, { "locale": "fr", "text": "Un faux restaurant pour tester l'ingestion de flux de points d'intérêt." } ], "default_locale": "en" }, "local_data": { "establishment_category": { "localizations": [ { "locale": "en", "text": "Restaurant" }, { "locale": "fr", "text": "Restaurant" } ], "default_locale": "en" }, "price_range": { "min_price": { "currency_code": "USD", "units": 15, "nanos": 0 }, "max_price": { "currency_code": "USD", "units": 45, "nanos": 0 } }, "business_hours": { "time_ranges": [ { "open_day": "MONDAY", "open_time": { "hours": 11, "minutes": 0 }, "close_day": "MONDAY", "close_time": { "hours": 21, "minutes": 0 } }, { "open_day": "TUESDAY", "open_time": { "hours": 11, "minutes": 0 }, "close_day": "TUESDAY", "close_time": { "hours": 21, "minutes": 0 } }, { "open_day": "WEDNESDAY", "open_time": { "hours": 11, "minutes": 0 }, "close_day": "WEDNESDAY", "close_time": { "hours": 21, "minutes": 0 } }, { "open_day": "THURSDAY", "open_time": { "hours": 11, "minutes": 0 }, "close_day": "THURSDAY", "close_time": { "hours": 22, "minutes": 0 } }, { "open_day": "FRIDAY", "open_time": { "hours": 11, "minutes": 0 }, "close_day": "FRIDAY", "close_time": { "hours": 23, "minutes": 0 } }, { "open_day": "SATURDAY", "open_time": { "hours": 10, "minutes": 0 }, "close_day": "SATURDAY", "close_time": { "hours": 23, "minutes": 0 } }, { "open_day": "SUNDAY", "open_time": { "hours": 10, "minutes": 0 }, "close_day": "SUNDAY", "close_time": { "hours": 20, "minutes": 0 } } ] }, "brand_landing_pages": [ { "brand_id": "tasty_bites_brand", "localized_landing_pages": [ { "url": "https://www.tastybitestest.com/fr", "locales": ["fr-FR", "fr-CA"] }, { "url": "https://www.tastybitestest.com/en", "locales": ["en-US", "en-GB"] } ], "default_url": "https://www.tastybitestest.com" } ] } } ] }