Place Autocomplete Data API

歐洲經濟區 (EEA) 開發人員

Place Autocomplete Data API 可讓您以程式輔助方式擷取地點預測結果,藉此建立自訂自動完成體驗,並提供比自動完成小工具更精細的控制程度。本指南說明如何使用 Place Autocomplete Data API,根據使用者查詢提出自動完成要求。

以下範例顯示簡化的自動完成整合。輸入搜尋查詢,例如「披薩」或「夏威夷生魚飯」,然後按一下選取所需結果。

Autocomplete 要求

自動完成要求會接收查詢輸入字串,並傳回地點預測結果清單。如要提出自動完成要求,請呼叫 fetchAutocompleteSuggestions(),並傳遞含有必要屬性的要求。input 屬性包含要搜尋的字串;在一般應用程式中,這個值會在使用者輸入查詢時更新。要求應包含 sessionToken,用於計費。

下列程式碼片段顯示如何建立要求主體、新增工作階段權杖,然後呼叫 fetchAutocompleteSuggestions() 取得 PlacePrediction 清單。

// Add an initial request body.
let request = {
    input: 'Tadi',
    locationRestriction: {
        west: -122.44,
        north: 37.8,
        east: -122.39,
        south: 37.78,
    },
    origin: { lat: 37.7893, lng: -122.4039 },
    includedPrimaryTypes: ['restaurant'],
    language: 'en-US',
    region: 'us',
};
// Create a session token.
const token = new AutocompleteSessionToken();
// Add the token to the request.
// @ts-ignore
request.sessionToken = token;

限制 Autocomplete 預測結果

根據預設,Place Autocomplete 會顯示所有地點類型 (優先顯示使用者所在位置附近的預測結果),並擷取使用者所選地點的所有可用資料欄位。您可以限制或自訂調整結果,將 Place Autocomplete 選項設為顯示更相關的預測結果。

限制結果後,Autocomplete 小工具會略過超出限制區域的所有結果。常見做法是將結果限制在地圖範圍內。自訂調整結果會讓 Autocomplete 小工具顯示指定區域內的結果,但有些相符項目可能會超出這個區域。

使用 origin 屬性指定起點,以便計算與目的地的測地距離。如果省略這個值,系統就不會傳回距離。

使用 includedPrimaryTypes 屬性指定最多五個地點類型。如未指定類型,系統會傳回所有類型的地點。

參閱 API 參考資料

取得 Place Details

如要從地點預測結果傳回 Place 物件,請先呼叫 toPlace(),然後在產生的 Place 物件上呼叫 fetchFields() (系統會自動納入地點預測的會期 ID)。呼叫 fetchFields() 會結束自動完成工作階段。

let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place.
await place.fetchFields({
    fields: ['displayName', 'formattedAddress'],
});
const placeInfo = document.getElementById('prediction');
placeInfo.textContent = `First predicted place: ${place.displayName}: ${place.formattedAddress}`;

工作階段符記

工作階段符記會將使用者自動完成搜尋的查詢和選取階段歸入不同的工作階段,以用於計費。工作階段會在使用者開始輸入時啟動。 使用者選取地點並呼叫 Place Details 時,工作階段就會結束。

如要建立新的工作階段符記並新增至要求,請建立 AutocompleteSessionToken 的例項,然後將要求的 sessionToken 屬性設為使用符記,如以下程式碼片段所示:

// Create a session token.
const token = new AutocompleteSessionToken();
// Add the token to the request.
// @ts-ignore
request.sessionToken = token;

呼叫 fetchFields() 時,工作階段就會結束。建立 Place 執行個體後,您不必將工作階段權杖傳遞至 fetchFields(),因為系統會自動處理這項作業。

await place.fetchFields({
    fields: ['displayName', 'formattedAddress'],
});

建立 AutocompleteSessionToken 的新例項,為下一個工作階段建立工作階段符記。

工作階段符記建議:

  • 在所有 Place Autocomplete 呼叫中使用工作階段符記。
  • 為每個工作階段產生新的權杖。
  • 請務必針對每個新的工作階段傳遞不重複的工作階段符記。如果多個工作階段使用同一個符記,則每個要求會分別計費。

您可以選擇從要求中省略自動完成工作階段符記。如果省略工作階段符記,系統會針對每個要求分別收費,並觸發 Autocomplete - Per Request SKU。假如您重複使用工作階段符記,系統會將工作階段視為無效,並針對相關要求收費 (因為系統會將其視為未提供工作階段符記)。

範例

使用者輸入查詢時,系統每隔幾次按鍵就會呼叫一次自動完成要求 (而非每個字元),並傳回可能的結果清單。使用者從結果清單中選取項目時,系統會將該選取項目視為一項要求,並將搜尋期間的所有要求一併計為一項要求。如果使用者選取地點,系統不會收取搜尋查詢費用,只會針對地點資料要求收費。如果使用者在工作階段開始後幾分鐘內未選取任何項目,系統只會收取搜尋查詢費用。

從應用程式的角度來看,事件流程如下:

  1. 使用者開始輸入查詢,搜尋「法國巴黎」。
  2. 偵測到使用者輸入內容後,應用程式會建立新的工作階段符記「Token A」。
  3. 使用者輸入時,API 會每隔幾個字元發出自動完成要求,並為每個要求顯示潛在結果的新清單:
    「P」
    「Par」
    「Paris」
    「Paris, Fr」
  4. 使用者選取項目時:
    • 查詢產生的所有要求都會分組,並以單一要求的形式,新增至以「權杖 A」表示的工作階段。
    • 系統會將使用者的選取項目計為 Place Detail 要求,並加入以「符記 A」表示的工作階段。
  5. 工作階段結束,應用程式會捨棄「權杖 A」。
瞭解工作階段的計費方式

完整程式碼範例

本節提供完整範例,說明如何使用 Place Autocomplete Data API。

地點自動完成預測

以下範例示範如何針對輸入內容「Tadi」呼叫 fetchAutocompleteSuggestions(),然後對第一個預測結果呼叫 toPlace(),接著呼叫 fetchFields() 取得地點詳細資料。

TypeScript

async function init() {
    const { Place, AutocompleteSessionToken, AutocompleteSuggestion } =
        (await google.maps.importLibrary(
            'places'
        )) as google.maps.PlacesLibrary;

    // Add an initial request body.
    let request = {
        input: 'Tadi',
        locationRestriction: {
            west: -122.44,
            north: 37.8,
            east: -122.39,
            south: 37.78,
        },
        origin: { lat: 37.7893, lng: -122.4039 },
        includedPrimaryTypes: ['restaurant'],
        language: 'en-US',
        region: 'us',
    };

    // Create a session token.
    const token = new AutocompleteSessionToken();
    // Add the token to the request.
    // @ts-ignore
    request.sessionToken = token;
    // Fetch autocomplete suggestions.
    const { suggestions } =
        await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);

    const title = document.getElementById('title') as HTMLElement;
    title.appendChild(
        document.createTextNode(
            'Query predictions for "' + request.input + '":'
        )
    );

    const resultsElement = document.getElementById('results') as HTMLElement;

    for (let suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;

        // Create a new list element.
        const listItem = document.createElement('li');

        listItem.appendChild(
            document.createTextNode(placePrediction!.text.toString())
        );
        resultsElement.appendChild(listItem);
    }

    let place = suggestions[0].placePrediction!.toPlace(); // Get first predicted place.
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress'],
    });

    const placeInfo = document.getElementById('prediction') as HTMLElement;
    placeInfo.textContent = `First predicted place: ${place.displayName}: ${place.formattedAddress}`;
}

init();

JavaScript

async function init() {
    const { Place, AutocompleteSessionToken, AutocompleteSuggestion } = (await google.maps.importLibrary('places'));
    // Add an initial request body.
    let request = {
        input: 'Tadi',
        locationRestriction: {
            west: -122.44,
            north: 37.8,
            east: -122.39,
            south: 37.78,
        },
        origin: { lat: 37.7893, lng: -122.4039 },
        includedPrimaryTypes: ['restaurant'],
        language: 'en-US',
        region: 'us',
    };
    // Create a session token.
    const token = new AutocompleteSessionToken();
    // Add the token to the request.
    // @ts-ignore
    request.sessionToken = token;
    // Fetch autocomplete suggestions.
    const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);
    const title = document.getElementById('title');
    title.appendChild(document.createTextNode('Query predictions for "' + request.input + '":'));
    const resultsElement = document.getElementById('results');
    for (let suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;
        // Create a new list element.
        const listItem = document.createElement('li');
        listItem.appendChild(document.createTextNode(placePrediction.text.toString()));
        resultsElement.appendChild(listItem);
    }
    let place = suggestions[0].placePrediction.toPlace(); // Get first predicted place.
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress'],
    });
    const placeInfo = document.getElementById('prediction');
    placeInfo.textContent = `First predicted place: ${place.displayName}: ${place.formattedAddress}`;
}
init();

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
#map {
    height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
    height: 100%;
    margin: 0;
    padding: 0;
}

HTML

<html>
    <head>
        <title>Place Autocomplete Data API Predictions</title>

        <link rel="stylesheet" type="text/css" href="./style.css" />
        <script type="module" src="./index.js"></script>
        <!-- prettier-ignore -->
        <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
        ({key: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly"});</script>
    </head>
    <body>
        <div id="title"></div>
        <ul id="results"></ul>
        <p><span id="prediction"></span></p>
        <img
            class="powered-by-google"
            src="./powered_by_google_on_white.png"
            alt="Powered by Google" />
    </body>
</html>

試用範例

使用工作階段的 Place Autocomplete 預先輸入功能

這個範例將說明下列概念:

  • 根據使用者查詢呼叫 fetchAutocompleteSuggestions(),並顯示預測地點清單做為回應。
  • 使用工作階段符記,將使用者查詢與最終的 Place Details 要求分組。
  • 擷取所選地點的 Place Details,並顯示標記。
  • 使用控制項插槽,將 UI 元素巢狀內嵌在 gmp-map 元素中。

TypeScript

const mapElement = document.querySelector('gmp-map') as google.maps.MapElement;
let innerMap: google.maps.Map;
let marker: google.maps.marker.AdvancedMarkerElement;
let titleElement = document.querySelector('.title') as HTMLElement;
let resultsContainerElement = document.querySelector('.results') as HTMLElement;
let inputElement = document.querySelector('input') as HTMLInputElement;
let tokenStatusElement = document.querySelector('.token-status') as HTMLElement;
let newestRequestId = 0;
let tokenCount = 0;

// Create an initial request body.
const request: google.maps.places.AutocompleteRequest = {
    input: '',
    includedPrimaryTypes: [
        'restaurant',
        'cafe',
        'museum',
        'park',
        'botanical_garden',
    ],
};

async function init() {
    await google.maps.importLibrary('maps');
    innerMap = mapElement.innerMap;
    innerMap.setOptions({
        mapTypeControl: false,
    });

    // Update request center and bounds when the map bounds change.
    google.maps.event.addListener(innerMap, 'bounds_changed', async () => {
        request.locationRestriction = innerMap.getBounds();
        request.origin = innerMap.getCenter();
    });

    inputElement.addEventListener('input', makeAutocompleteRequest);
}

async function makeAutocompleteRequest(inputEvent) {
    // To avoid race conditions, store the request ID and compare after the request.
    const requestId = ++newestRequestId;

    const { AutocompleteSuggestion } = (await google.maps.importLibrary(
        'places'
    )) as google.maps.PlacesLibrary;

    if (!inputEvent.target?.value) {
        titleElement.textContent = '';
        resultsContainerElement.replaceChildren();
        return;
    }

    // Add the latest char sequence to the request.
    request.input = (inputEvent.target as HTMLInputElement).value;

    // Fetch autocomplete suggestions and show them in a list.
    const { suggestions } =
        await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);

    // If the request has been superseded by a newer request, do not render the output.
    if (requestId !== newestRequestId) return;

    titleElement.innerText = `Place predictions for "${request.input}"`;

    // Clear the list first.
    resultsContainerElement.replaceChildren();

    for (const suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;

        if (!placePrediction) {
            continue;
        }

        // Create a link for the place, add an event handler to fetch the place.
        // We are using a button element to take advantage of its a11y capabilities.
        const placeButton = document.createElement('button');
        placeButton.addEventListener('click', () => {
            onPlaceSelected(placePrediction.toPlace());
        });
        placeButton.textContent = placePrediction.text.toString();
        placeButton.classList.add('place-button');

        // Create a new list item element.
        const li = document.createElement('li');
        li.appendChild(placeButton);
        resultsContainerElement.appendChild(li);
    }
}

// Event handler for clicking on a suggested place.
async function onPlaceSelected(place: google.maps.places.Place) {
    const { AdvancedMarkerElement } = (await google.maps.importLibrary(
        'marker'
    )) as google.maps.MarkerLibrary;

    await place.fetchFields({
        fields: ['displayName', 'formattedAddress', 'location'],
    });

    resultsContainerElement.textContent = `${place.displayName}: ${place.formattedAddress}`;
    titleElement.textContent = 'Selected Place:';
    inputElement.value = '';

    await refreshToken();

    // Remove the previous marker, if it exists.
    if (marker) {
        marker.remove();
    }

    // Create a new marker.
    marker = new AdvancedMarkerElement({
        map: innerMap,
        position: place.location,
        title: place.displayName,
    });

    // Center the map on the selected place.
    if (place.location) {
        innerMap.setCenter(place.location);
        innerMap.setZoom(15);
    }
}

// Helper function to refresh the session token.
async function refreshToken() {
    const { AutocompleteSessionToken } = (await google.maps.importLibrary(
        'places'
    )) as google.maps.PlacesLibrary;

    // Increment the token counter.
    tokenCount++;

    // Create a new session token and add it to the request.
    request.sessionToken = new AutocompleteSessionToken();
    tokenStatusElement.textContent = `Session token count: ${tokenCount}`;
}

init();

JavaScript

const mapElement = document.querySelector('gmp-map');
let innerMap;
let marker;
let titleElement = document.querySelector('.title');
let resultsContainerElement = document.querySelector('.results');
let inputElement = document.querySelector('input');
let tokenStatusElement = document.querySelector('.token-status');
let newestRequestId = 0;
let tokenCount = 0;
// Create an initial request body.
const request = {
    input: '',
    includedPrimaryTypes: [
        'restaurant',
        'cafe',
        'museum',
        'park',
        'botanical_garden',
    ],
};
async function init() {
    await google.maps.importLibrary('maps');
    innerMap = mapElement.innerMap;
    innerMap.setOptions({
        mapTypeControl: false,
    });
    // Update request center and bounds when the map bounds change.
    google.maps.event.addListener(innerMap, 'bounds_changed', async () => {
        request.locationRestriction = innerMap.getBounds();
        request.origin = innerMap.getCenter();
    });
    inputElement.addEventListener('input', makeAutocompleteRequest);
}
async function makeAutocompleteRequest(inputEvent) {
    // To avoid race conditions, store the request ID and compare after the request.
    const requestId = ++newestRequestId;
    const { AutocompleteSuggestion } = (await google.maps.importLibrary('places'));
    if (!inputEvent.target?.value) {
        titleElement.textContent = '';
        resultsContainerElement.replaceChildren();
        return;
    }
    // Add the latest char sequence to the request.
    request.input = inputEvent.target.value;
    // Fetch autocomplete suggestions and show them in a list.
    const { suggestions } = await AutocompleteSuggestion.fetchAutocompleteSuggestions(request);
    // If the request has been superseded by a newer request, do not render the output.
    if (requestId !== newestRequestId)
        return;
    titleElement.innerText = `Place predictions for "${request.input}"`;
    // Clear the list first.
    resultsContainerElement.replaceChildren();
    for (const suggestion of suggestions) {
        const placePrediction = suggestion.placePrediction;
        if (!placePrediction) {
            continue;
        }
        // Create a link for the place, add an event handler to fetch the place.
        // We are using a button element to take advantage of its a11y capabilities.
        const placeButton = document.createElement('button');
        placeButton.addEventListener('click', () => {
            onPlaceSelected(placePrediction.toPlace());
        });
        placeButton.textContent = placePrediction.text.toString();
        placeButton.classList.add('place-button');
        // Create a new list item element.
        const li = document.createElement('li');
        li.appendChild(placeButton);
        resultsContainerElement.appendChild(li);
    }
}
// Event handler for clicking on a suggested place.
async function onPlaceSelected(place) {
    const { AdvancedMarkerElement } = (await google.maps.importLibrary('marker'));
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress', 'location'],
    });
    resultsContainerElement.textContent = `${place.displayName}: ${place.formattedAddress}`;
    titleElement.textContent = 'Selected Place:';
    inputElement.value = '';
    await refreshToken();
    // Remove the previous marker, if it exists.
    if (marker) {
        marker.remove();
    }
    // Create a new marker.
    marker = new AdvancedMarkerElement({
        map: innerMap,
        position: place.location,
        title: place.displayName,
    });
    // Center the map on the selected place.
    if (place.location) {
        innerMap.setCenter(place.location);
        innerMap.setZoom(15);
    }
}
// Helper function to refresh the session token.
async function refreshToken() {
    const { AutocompleteSessionToken } = (await google.maps.importLibrary('places'));
    // Increment the token counter.
    tokenCount++;
    // Create a new session token and add it to the request.
    request.sessionToken = new AutocompleteSessionToken();
    tokenStatusElement.textContent = `Session token count: ${tokenCount}`;
}
init();

CSS

/* 
 * Always set the map height explicitly to define the size of the div element
 * that contains the map. 
 */
gmp-map {
    height: 100%;
}

/* 
 * Optional: Makes the sample page fill the window. 
 */
html,
body {
    height: 100%;
    margin: 0;
    padding: 0;
}

.place-button {
    height: 3rem;
    width: 100%;
    background-color: transparent;
    text-align: left;
    border: none;
    cursor: pointer;
}

.place-button:focus-visible {
    outline: 2px solid #0056b3;
    border-radius: 2px;
}

.input {
    width: 300px;
    font-size: small;
    margin-bottom: 1rem;
}

/* Styles for the floating panel */
.controls {
    background-color: #fff;
    border-radius: 8px;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
    font-family: sans-serif;
    font-size: small;
    margin: 12px;
    padding: 1rem;
}

.title {
    font-weight: bold;
    margin-top: 1rem;
    margin-bottom: 0.5rem;
}

.results {
    list-style-type: none;
    margin: 0;
    padding: 0;
}

.results li:not(:last-child) {
    border-bottom: 1px solid #ddd;
}

.results li:hover {
    background-color: #eee;
}

HTML

<html>
    <head>
        <title>Place Autocomplete Data API Session</title>

        <link rel="stylesheet" type="text/css" href="./style.css" />
        <script type="module" src="./index.js"></script>
        <!-- prettier-ignore -->
        <script>(g=>{var h,a,k,p="The Google Maps JavaScript API",c="google",l="importLibrary",q="__ib__",m=document,b=window;b=b[c]||(b[c]={});var d=b.maps||(b.maps={}),r=new Set,e=new URLSearchParams,u=()=>h||(h=new Promise(async(f,n)=>{await (a=m.createElement("script"));e.set("libraries",[...r]+"");for(k in g)e.set(k.replace(/[A-Z]/g,t=>"_"+t[0].toLowerCase()),g[k]);e.set("callback",c+".maps."+q);a.src=`https://maps.${c}apis.com/maps/api/js?`+e;d[q]=f;a.onerror=()=>h=n(Error(p+" could not load."));a.nonce=m.querySelector("script[nonce]")?.nonce||"";m.head.append(a)}));d[l]?console.warn(p+" only loads once. Ignoring:",g):d[l]=(f,...n)=>r.add(f)&&u().then(()=>d[l](f,...n))})
        ({key: "AIzaSyA6myHzS10YXdcazAFalmXvDkrYCp5cLc8", v: "weekly"});</script>
    </head>
    <body>
        <gmp-map center="37.7893, -122.4039" zoom="12" map-id="DEMO_MAP_ID">
            <div class="controls" slot="control-inline-start-block-start">
                <input
                    type="text"
                    class="input"
                    placeholder="Search for a place..."
                    autocomplete="off" /><!-- Turn off the input's own autocomplete (not supported by all browsers).-->
                <div class="token-status"></div>
                <div class="title"></div>
                <ol class="results"></ol>
            </div>
        </gmp-map>
    </body>
</html>

試用範例

Autocomplete (新版) 最佳化

本節將說明最佳做法,協助您充分運用 Autocomplete (New) 服務。

以下列出幾項一般準則:

  • 如要開發有效的使用者介面,最快的方法就是使用 Maps JavaScript API Autocomplete (New) 小工具、 Places SDK for Android Autocomplete (New) 小工具, 或 Places SDK for iOS Autocomplete (New) 小工具
  • 從一開始就瞭解 Autocomplete (新版) 的必要資料欄位
  • 「位置自訂調整」和「位置限制」為自選欄位,但可能會對自動完成效能產生重大影響。
  • 使用錯誤處理機制,可以減輕 API 傳回錯誤時對應用程式效能造成的影響。
  • 確保應用程式能處理未選取任何項目的情況,以便使用者繼續操作。

費用最佳化最佳做法

基本費用最佳化

為了讓 Autocomplete (New) 服務費用發揮最大效益,請使用 Place Details (New) 和 Autocomplete (New) 小工具中的欄位遮罩,只傳回所需的 Autocomplete (New) 資料欄位

進階費用最佳化

建議您透過程式輔助方式導入 Autocomplete (New),採用SKU:Autocomplete Request 計價,並要求已選地點 (而非 Place Details (New)) 的相關 Geocoding API 結果。如果同時符合以下兩項條件,搭配 Geocoding API 使用「按要求」計價會比使用「按工作階段」(以工作階段為準) 計價更具成本效益:

  • 如果您只需要針對使用者選取的地點取得經緯度或地址,透過 Geocoding API 擷取這項資訊,支付的費用會比使用 Place Details (New) 呼叫更低。
  • 如果使用者在平均四次以內的自動預測結果要求選取了自動預測結果,則「按要求」計價可能會比「按工作階段」計價更符合成本效益。
如要瞭解如何選取符合需求的 Autocomplete (New) 導入方式,請回答下列問題,並選取對應的分頁標籤。

除了所選預測結果的地址和經緯度,應用程式是否需要任何其他資訊?

是,需要更多詳細資料

搭配 Place Details (新版) 使用以工作階段為準的 Autocomplete (新版)。
由於應用程式需要地點詳細資料 (新版),例如地點名稱、商家狀態或營業時間,因此實作 Autocomplete (新版) 時,應使用JavaScriptAndroidiOS 小工具中內建的每個工作階段工作階段符記,以及適用的 Places SKU,具體取決於您要求哪些地點資料欄位。1

透過小工具導入
JavaScriptAndroidiOS 小工具自動內建工作階段管理功能,其中包含對已選取的預測結果提出的 Autocomplete (新版) 要求和 Place Details (新版) 要求。請務必指定 fields 參數,確保只要求所需的 Autocomplete (New) 資料欄位

透過程式輔助方式導入
搭配 Autocomplete (New) 要求使用工作階段符記。要求所選預測結果的相關 Place Details (新版) 時,請加入下列參數:

  1. Autocomplete (新版) 回應中的地點 ID
  2. Autocomplete (New) 要求中使用的工作階段符記
  3. 指定所需 Autocomplete (新版) 資料欄位fields 參數

否,只需要地址和位置資訊

對您的應用程式而言,Geocoding API 可能比 Place Details (New) 更符合成本效益,視 Autocomplete (New) 使用效能而定。每個應用程式的自動完成 (新版) 效率各不相同,可能取決於使用者輸入的內容、使用應用程式的位置,以及是否採用效能最佳化最佳做法

為了找出以下問題的解答,請分析使用者在應用程式中選取 Autocomplete (New) 預測結果前,平均輸入的字元數量。

使用者是否會在平均四次以內的要求中選取 Autocomplete (New) 預測結果?

透過程式輔助方式導入 Autocomplete (New),但不使用工作階段符記,並針對已選取的地點預測結果呼叫 Geocoding API。
Geocoding API 提供地址和經緯度座標。 提出四次自動完成要求,加上所選地點預測結果的相關 Geocoding API 呼叫,總費用會低於自動完成 (新版) 功能「按工作階段」計價的每個工作階段費用1

建議您採用效能最佳做法,讓使用者以更少的字元找到需要的預測結果。

搭配 Place Details (新版) 使用以工作階段為準的 Autocomplete (新版)。
由於您預期在使用者選取 Autocomplete (新版) 預測結果前,平均會發出超過「按工作階段」計價費用的要求,因此 Autocomplete (新版) 的實作應針對 Autocomplete (新版) 要求和相關聯的 Place Details (新版) 要求,使用按工作階段計價的工作階段符記。 1

透過小工具導入
JavaScriptAndroidiOS 小工具自動內建工作階段管理功能,其中包含對已選取的預測結果提出的 Autocomplete (新版) 要求和 Place Details (新版) 要求。請務必指定 fields 參數,確保只要求所需的欄位。

透過程式輔助方式導入
搭配 Autocomplete (New) 要求使用工作階段符記。要求所選預測結果的相關 Place Details (新版) 時,請加入下列參數:

  1. Autocomplete (新版) 回應中的地點 ID
  2. Autocomplete (New) 要求中使用的工作階段符記
  3. 指定地址和幾何圖形等欄位的 fields 參數

考慮延後 Autocomplete (New) 要求
您可以運用一些策略,例如將 Autocomplete (New) 要求延後到使用者輸入三或四個字元時再開始,藉此減少應用程式提出要求數量。舉例來說,如果使用者輸入第三個字元後,您為每個字元提出自動完成 (新版) 要求,則使用者輸入七個字元並選取預測結果後,您提出一次 Geocoding API 要求,總費用會是 4 次自動完成 (新版) 要求 + Geocoding。1

如果延後要求可以讓平均程式輔助要求少於四次,您可以按照使用 Geocoding API 提高 Autocomplete (New) 效能的指南操作。請注意,如果使用者希望每輸入一個字就能看到預測結果,可能就會將延後要求視為時間上的延遲。

建議您採用效能最佳做法,讓使用者以更少的字元找到需要的預測結果。


  1. 如要瞭解費用,請參閱 Google 地圖平台價目表

效能最佳做法

以下準則說明如何將 Autocomplete (新版) 效能最佳化:

  • 針對導入的 Autocomplete (New) 加入國家/地區限制、位置自訂調整和 (適用於程式輔助導入) 語言偏好設定。小工具會從使用者的瀏覽器或行動裝置選擇語言偏好設定,因此不需要設定語言偏好。
  • 如果 Autocomplete (New) 附帶地圖,您就可以根據地圖可視區域進行位置自訂調整。
  • 如果使用者沒有選擇任何自動完成 (新版) 預測結果 (通常是因為這些預測結果並非他們想要的地址),您可以重複使用原始使用者輸入內容,嘗試取得更相關的結果:
    • 如果您預期使用者只會輸入地址資訊,請在 Geocoding API 呼叫中重複使用原始使用者輸入內容。
    • 如果您預期使用者會依名稱或地址查詢某個地點,請使用 Place Details (New) 要求。如果希望將結果範圍限制在特定區域,請使用位置自訂調整
    適合改回使用 Geocoding API 的其他情況如下:
    • 使用者輸入子處所地址,例如建築物內特定單位或公寓的地址。例如,捷克地址「Stroupežnického 3191/17, Praha」在 Autocomplete (新版) 中會產生不完整的預測結果。
    • 使用者輸入的地址含有路段前置字元,例如紐約的「23-30 29th St, Queens」或夏威夷考艾島的「47-380 Kamehameha Hwy, Kaneohe」。

位置偏誤

傳遞 location 參數和 radius 參數,針對特定區域調整結果。這會指示 Autocomplete (New) 優先顯示定義區域內的結果。不過,系統還是有可能會顯示定義區域外的結果。您可以使用 components 參數篩選結果,只顯示特定國家/地區內的地點。

限制位置

傳送 locationRestriction 參數,將結果限制在特定區域。

您也可以新增 locationRestriction 參數,將結果限制在 locationradius 參數定義的區域內。這會指示 Autocomplete (New) 傳回該區域內的結果。