API Place Autocomplete Data

Com a API Place Autocomplete Data, é possível buscar previsões de lugares de maneira programática para criar experiências personalizadas de preenchimento automático com um maior grau de controle do que com o widget desse recurso. Neste guia, você vai aprender a usar a API Place Autocomplete Data para fazer solicitações de preenchimento automático com base nas consultas dos usuários.

O exemplo a seguir mostra uma integração simples com antecedência. Digite sua consulta de pesquisa e clique para selecionar o resultado desejado.

Solicitações de Autocomplete

Uma solicitação de preenchimento automático usa uma string de entrada de consulta e retorna uma lista de previsões de locais. Para fazer uma solicitação de preenchimento automático, chame fetchAutocompleteSuggestions() e transmita uma solicitação com as propriedades necessárias. A propriedade input contém a string a ser pesquisada. Em um aplicativo comum, esse valor é atualizado à medida que o usuário digita uma consulta. A solicitação precisa incluir um sessionToken, que é usado para fins de faturamento.

O snippet a seguir mostra como criar um corpo de solicitação e adicionar um token de sessão e, em seguida, chamar fetchAutocompleteSuggestions() para receber uma lista de PlacePredictions.

// 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;

Restringir previsões de preenchimento automático

Por padrão, o Place Autocomplete apresenta todos os tipos de lugares, favorece previsões perto da localização do usuário e busca todos os campos de dados disponíveis para o lugar que a pessoa selecionou. Defina as opções do Place Autocomplete para mostrar previsões mais relevantes restringindo ou polarizando os resultados.

Quando você restringe os resultados, o widget de preenchimento automático ignora os resultados que estão fora da área de restrição. Uma prática comum é restringir os resultados aos limites do mapa. A polarização de resultados faz com que o widget de preenchimento automático mostre resultados dentro da área especificada, mas algumas correspondências podem estar fora dessa região.

Use a propriedade origin para especificar o ponto de origem a partir do qual a distância geodésica será calculada até o destino. Se esse valor for omitido, a distância não será retornada.

Use a propriedade includedPrimaryTypes para especificar até cinco tipos de lugar. Se nenhum tipo for especificado, lugares de todos os tipos serão retornados.

Consulte a Referência da API

Conferir detalhes sobre o lugar

Para retornar um objeto Place de um resultado de previsão de lugar, primeiro chame toPlace() e, em seguida, chame fetchFields() no objeto Place resultante (o ID da sessão da previsão de lugar é incluído automaticamente). Chamar fetchFields() encerra a sessão de preenchimento automático.

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;

Tokens de sessão

Os tokens de sessão agrupam as fases de consulta e seleção de uma pesquisa de preenchimento automático do usuário em uma sessão discreta para fins de faturamento. A sessão começa quando o usuário começa a digitar. A sessão termina quando o usuário seleciona um lugar e faz uma chamada para o Place Details.

Para criar um novo token de sessão e adicioná-lo a uma solicitação, crie uma instância de AutocompleteSessionToken e defina a propriedade sessionToken da solicitação para usar os tokens, conforme mostrado no snippet a seguir:

// Create a session token.
const token = new AutocompleteSessionToken();

// Add the token to the request.
// @ts-ignore
request.sessionToken = token;

Uma sessão é concluída quando fetchFields() é chamado. Depois de criar a instância Place, não é preciso transmitir o token de sessão para fetchFields(), porque isso é processado automaticamente.

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

Para gerar um token de sessão para a próxima sessão, crie uma nova instância de AutocompleteSessionToken.

Recomendações de tokens de sessão:

  • Usar tokens de sessão para todas as chamadas do Place Autocomplete.
  • Gerar um novo token para cada sessão.
  • Transmita um token de sessão exclusivo para cada nova sessão. Se você usar o mesmo token para mais de uma sessão, cada solicitação será faturada individualmente.

Você tem a opção de omitir o token da sessão de preenchimento automático de uma solicitação. Se o token de sessão for omitido, cada solicitação será faturada separadamente, acionando a SKU Autocomplete – por solicitação. Se você reutilizar um token, a sessão será considerada inválida, e as solicitações serão cobradas como se nenhum token de sessão tivesse sido fornecido.

Exemplo

À medida que o usuário digita uma consulta, uma solicitação de preenchimento automático é chamada a cada poucas teclas (não por caractere) e uma lista de resultados possíveis é retornada. Quando o usuário faz uma seleção na lista de resultados, a seleção conta como uma solicitação, e todas as solicitações feitas durante a pesquisa são agrupadas e contadas como uma única solicitação. Se o usuário selecionar um lugar, a consulta de pesquisa ficará disponível sem custos financeiros, e somente a solicitação de dados do lugar será cobrada. Se o usuário não fizer uma seleção alguns minutos depois do início da sessão, somente a consulta de pesquisa será cobrada.

Da perspectiva de um aplicativo, o fluxo de eventos é o seguinte:

  1. Um usuário começa a digitar uma consulta para pesquisar "Paris, França".
  2. Ao detectar a entrada do usuário, o app cria um novo token de sessão, o "token A".
  3. À medida que o usuário digita, a API faz uma solicitação de preenchimento automático a cada alguns caracteres, mostrando uma nova lista de possíveis resultados para cada um:
    "P"
    "Par"
    "Paris",
    "Paris, Sex"
  4. Quando o usuário faz uma seleção:
    • Todas as solicitações resultantes da consulta são agrupadas e adicionadas à sessão representada por "Token A" como uma única solicitação.
    • A seleção do usuário é contada como uma solicitação do Place Details e adicionada à sessão representada pelo "Token A".
  5. A sessão é concluída, e o app descarta o "Token A".
Saiba como as sessões são faturadas

Exemplo de código completo

Esta seção contém exemplos completos que mostram como usar a API Place Autocomplete Data .

Previsões de preenchimento automático de lugares

O exemplo a seguir demonstra como chamar fetchAutocompleteSuggestions() para a entrada "Tadi" e depois chamar toPlace() no primeiro resultado da previsão, seguido de uma chamada para fetchFields() para ver detalhes do lugar.

TypeScript

/**
 * Demonstrates making a single request for Place predictions, then requests Place Details for the first result.
 */
async function init() {
    // @ts-ignore
    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 + '":'));

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

        // Create a new list element.
        const listItem = document.createElement('li');
        const resultsElement = document.getElementById("results") as HTMLElement;
        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

/**
 * Demonstrates making a single request for Place predictions, then requests Place Details for the first result.
 */
async function init() {
  // @ts-ignore
  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 + '":'),
  );

  for (let suggestion of suggestions) {
    const placePrediction = suggestion.placePrediction;
    // Create a new list element.
    const listItem = document.createElement("li");
    const resultsElement = document.getElementById("results");

    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>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <div id="title"></div>
    <ul id="results"></ul>
    <p><span id="prediction"></span></p>
    <img
      class="powered-by-google"
      src="https://storage.googleapis.com/geo-devrel-public-buckets/powered_by_google_on_white.png"
      alt="Powered by Google"
    />

    <!-- 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: "AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg", v: "weekly"});</script>
  </body>
</html>

Testar amostra

JSFiddle.net (link em inglês) Google Cloud Shell

Posicionar o preenchimento automático manualmente com sessões

Neste exemplo, mostramos como chamar fetchAutocompleteSuggestions() com base nas consultas do usuário, mostrar uma lista de locais previstos em resposta e, por fim, recuperar detalhes do lugar selecionado. O exemplo também demonstra o uso de tokens de sessão para agrupar uma consulta do usuário com a solicitação final do Place Details.

TypeScript

let title;
let results;
let input;
let token;

// Add an initial request body.
let request = {
    input: "",
    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",
};

async function init() {
    token = new google.maps.places.AutocompleteSessionToken();

    title = document.getElementById('title');
    results = document.getElementById('results');
    input = document.querySelector("input");
    input.addEventListener("input", makeAcRequest);
    request = refreshToken(request) as any;
}

async function makeAcRequest(input) {
    // Reset elements and exit if an empty string is received.
    if (input.target.value == '') {
        title.innerText = '';
        results.replaceChildren();
        return;
    }

    // Add the latest char sequence to the request.
    request.input = input.target.value;

    // Fetch autocomplete suggestions and show them in a list.
    // @ts-ignore
    const { suggestions } = await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(request);

    title.innerText = 'Query predictions for "' + request.input + '"';

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

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

        // Create a link for the place, add an event handler to fetch the place.
        const a = document.createElement('a');
        a.addEventListener('click', () => {
            onPlaceSelected(placePrediction.toPlace());
        });
        a.innerText = placePrediction.text.toString();

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

// Event handler for clicking on a suggested place.
async function onPlaceSelected(place) {
    await place.fetchFields({
        fields: ['displayName', 'formattedAddress'],
    });
    let placeText = document.createTextNode(place.displayName + ': ' + place.formattedAddress);
    results.replaceChildren(placeText);
    title.innerText = 'Selected Place:';
    input.value = '';
    refreshToken(request);
}

// Helper function to refresh the session token.
async function refreshToken(request) {
    // Create a new session token and add it to the request.
    token = new google.maps.places.AutocompleteSessionToken();
    request.sessionToken = token;
    return request;
}

declare global {
    interface Window {
      init: () => void;
    }
  }
  window.init = init;

JavaScript

let title;
let results;
let input;
let token;
// Add an initial request body.
let request = {
  input: "",
  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",
};

async function init() {
  token = new google.maps.places.AutocompleteSessionToken();
  title = document.getElementById("title");
  results = document.getElementById("results");
  input = document.querySelector("input");
  input.addEventListener("input", makeAcRequest);
  request = refreshToken(request);
}

async function makeAcRequest(input) {
  // Reset elements and exit if an empty string is received.
  if (input.target.value == "") {
    title.innerText = "";
    results.replaceChildren();
    return;
  }

  // Add the latest char sequence to the request.
  request.input = input.target.value;

  // Fetch autocomplete suggestions and show them in a list.
  // @ts-ignore
  const { suggestions } =
    await google.maps.places.AutocompleteSuggestion.fetchAutocompleteSuggestions(
      request,
    );

  title.innerText = 'Query predictions for "' + request.input + '"';
  // Clear the list first.
  results.replaceChildren();

  for (const suggestion of suggestions) {
    const placePrediction = suggestion.placePrediction;
    // Create a link for the place, add an event handler to fetch the place.
    const a = document.createElement("a");

    a.addEventListener("click", () => {
      onPlaceSelected(placePrediction.toPlace());
    });
    a.innerText = placePrediction.text.toString();

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

    li.appendChild(a);
    results.appendChild(li);
  }
}

// Event handler for clicking on a suggested place.
async function onPlaceSelected(place) {
  await place.fetchFields({
    fields: ["displayName", "formattedAddress"],
  });

  let placeText = document.createTextNode(
    place.displayName + ": " + place.formattedAddress,
  );

  results.replaceChildren(placeText);
  title.innerText = "Selected Place:";
  input.value = "";
  refreshToken(request);
}

// Helper function to refresh the session token.
async function refreshToken(request) {
  // Create a new session token and add it to the request.
  token = new google.maps.places.AutocompleteSessionToken();
  request.sessionToken = token;
  return request;
}

window.init = 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;
}

a {
  cursor: pointer;
  text-decoration: underline;
  color: blue;
}

input {
  width: 300px;
}

HTML

<html>
  <head>
    <title>Place Autocomplete Data API Session</title>
    <script src="https://polyfill.io/v3/polyfill.min.js?features=default"></script>

    <link rel="stylesheet" type="text/css" href="./style.css" />
    <script type="module" src="./index.js"></script>
  </head>
  <body>
    <input id="input" type="text" placeholder="Search for a place..." />
    <div id="title"></div>
    <ul id="results"></ul>
    <img
      class="powered-by-google"
      src="https://storage.googleapis.com/geo-devrel-public-buckets/powered_by_google_on_white.png"
      alt="Powered by Google"
    />

    <!-- 
      The `defer` attribute causes the script to execute after the full HTML
      document has been parsed. For non-blocking uses, avoiding race conditions,
      and consistent behavior across browsers, consider loading using Promises. See
      https://developers.google.com/maps/documentation/javascript/load-maps-js-api
      for more information.
      -->
    <script
      src="https://maps.googleapis.com/maps/api/js?key=AIzaSyB41DRUbKWJHPxaFjMAwdrzWzbVKartNGg&callback=init&libraries=places&v=weekly"
      defer
    ></script>
  </body>
</html>

Testar amostra

JSFiddle.net (link em inglês) Google Cloud Shell