API Place Autocomplete Data

L'API Place Autocomplete Data vous permet d'extraire des prédictions de lieux de manière programmatique, afin de créer des expériences de saisie semi-automatique personnalisées avec un niveau de contrôle plus précis qu'avec le widget de saisie semi-automatique. Dans ce guide, vous allez apprendre à utiliser l'API Place Autocomplete Data pour effectuer des requêtes de saisie semi-automatique basées sur les requêtes des utilisateurs.

L'exemple suivant illustre une intégration de saisie anticipée simple. Saisissez votre requête de recherche, puis cliquez pour sélectionner le résultat souhaité.

Requêtes Autocomplete

Une requête de saisie semi-automatique prend une chaîne d'entrée de requête et renvoie une liste de prédictions de lieux. Pour effectuer une requête de saisie semi-automatique, appelez fetchAutocompleteSuggestions() et transmettez une requête avec les propriétés requises. La propriété input contient la chaîne à rechercher. Dans une application classique, cette valeur est mise à jour lorsque l'utilisateur saisit une requête. La requête doit inclure un sessionToken, utilisé pour la facturation.

L'extrait de code suivant montre comment créer un corps de requête et ajouter un jeton de session, puis appeler fetchAutocompleteSuggestions() pour obtenir une liste d'éléments 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;

Limiter les prédictions de saisie semi-automatique

Par défaut, Place Autocomplete présente tous les types de lieux, avec une pondération en faveur des prédictions de lieux proches de l'utilisateur, et extrait tous les champs de données disponibles pour le lieu qu'il sélectionne. Définissez des options Place Autocomplete pour présenter des prédictions plus pertinentes en limitant ou en pondérant les résultats.

Si vous limitez les résultats, le widget Autocomplete ignore tous les résultats situés en dehors de la zone de restriction. Une pratique courante consiste à limiter les résultats aux limites de la carte. Pondérer la saisie semi-automatique permet d'afficher les résultats dans la zone spécifiée. Toutefois, certaines correspondances peuvent se trouver en dehors de cette zone.

Utilisez la propriété origin pour spécifier le point de départ à partir duquel calculer la distance géodésique jusqu'à la destination. Si cette valeur est omise, la distance n'est pas renvoyée.

Utilisez la propriété includedPrimaryTypes pour spécifier jusqu'à cinq types de lieux. Si aucun type n'est spécifié, les lieux de tous types sont renvoyés.

Voir la documentation de référence de l'API

Obtenir des informations sur un lieu

Pour renvoyer un objet Place à partir d'un résultat de prédiction de lieu, appelez d'abord toPlace(), puis fetchFields() sur l'objet Place obtenu (l'ID de session de la prédiction de lieu est automatiquement inclus). L'appel de fetchFields() met fin à la session de saisie semi-automatique.

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;

Jetons de session

Les jetons de session regroupent les phases de requête et de sélection d'une recherche avec saisie semi-automatique d'un utilisateur dans une session distincte à des fins de facturation. La session commence lorsque l'utilisateur commence à saisir du texte. La session se termine lorsque l'utilisateur sélectionne un lieu et qu'un appel à Place Details est effectué.

Pour créer un jeton de session et l'ajouter à une requête, créez une instance de AutocompleteSessionToken, puis définissez la propriété sessionToken de la requête afin d'utiliser les jetons, comme indiqué dans l'extrait suivant:

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

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

Une session se termine lorsque fetchFields() est appelé. Après avoir créé l'instance Place, vous n'avez pas besoin de transmettre le jeton de session à fetchFields(), car cette opération est gérée automatiquement.

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

Créez un jeton de session pour la session suivante en créant une instance de AutocompleteSessionToken.

Recommandations de jetons de session:

  • Utilisez des jetons de session pour tous les appels Place Autocomplete.
  • Générez un nouveau jeton pour chaque session.
  • Transmettez un jeton de session unique pour chaque nouvelle session. Si vous utilisez le même jeton pour plusieurs sessions, chaque requête sera facturée individuellement.

Vous pouvez éventuellement omettre le jeton de session de saisie semi-automatique d'une requête. Si le jeton de session est omis, chaque requête est facturée séparément, ce qui déclenche le SKU Autocomplete - Per Request. Si vous réutilisez un jeton de session, la session est considérée comme non valide, et les requêtes sont facturées comme si aucun jeton n'avait été fourni.

Exemple

Lorsque l'utilisateur saisit une requête, une requête de saisie semi-automatique est appelée au bout de quelques frappes (et non par caractère), et une liste des résultats possibles est renvoyée. Lorsque l'utilisateur effectue une sélection dans la liste des résultats, celle-ci est comptabilisée comme une requête. Toutes les requêtes effectuées lors de la recherche sont regroupées et comptabilisées comme une seule requête. Si l'utilisateur sélectionne un lieu, la requête de recherche est disponible sans frais, et seule la requête de données de lieu est facturée. Si l'utilisateur ne fait pas de sélection dans les quelques minutes qui suivent le début de la session, seule la requête de recherche est facturée.

Du point de vue d'une application, le flux d'événements se présente comme suit:

  1. Un utilisateur commence à saisir une requête pour rechercher "Paris, France".
  2. Lors de la détection d'une entrée utilisateur, l'application crée un jeton de session, "Jeton A".
  3. À mesure que l'utilisateur saisit du texte, l'API envoie une requête de saisie semi-automatique à un intervalle de quelques caractères, affichant une nouvelle liste de résultats potentiels pour chacun d'eux:
    "P"
    "Par"
    "Paris",
    "Paris, Fr"
  4. Lorsque l'utilisateur effectue une sélection :
    • Toutes les requêtes résultant de la requête sont regroupées et ajoutées à la session représentée par "Jeton A", sous la forme d'une requête unique.
    • La sélection de l'utilisateur est comptabilisée comme une requête Place Details et ajoutée à la session représentée par le "Jeton A".
  5. La session est terminée, et l'application supprime le "jeton A".
En savoir plus sur la facturation des sessions

Exemple de code complet

Cette section contient des exemples complets d'utilisation de l'API Place Autocomplete Data .

Prédictions de la saisie semi-automatique de lieu

L'exemple suivant montre comment appeler fetchAutocompleteSuggestions() pour l'entrée "Tadi", puis appeler toPlace() sur le premier résultat de prédiction, puis appeler fetchFields() pour obtenir des détails sur le lieu.

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>

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

Essayer avec un exemple

Placer la saisie semi-automatique à l'avance avec les sessions

Cet exemple montre comment appeler fetchAutocompleteSuggestions() en fonction des requêtes des utilisateurs, afficher une liste de lieux prédits en réponse et récupérer les détails sur le lieu sélectionné. L'exemple illustre également l'utilisation de jetons de session pour regrouper une requête utilisateur dans la requête Place Details finale.

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>

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

Essayer avec un exemple