Setting multi-location services

The following tutorial describes how to define multi-location services (e.g. services that span across multiple points of interests). This tutorial is most relevant for partners in the ticketing space.

Example use cases:

  • A one-day tour in San Francisco that starts from the Financial District and visits a few local attractions. Hotel pick-up is available at a few popular nearby hotels
  • A hop-on, hop-off bus tour in Paris where the user can choose to visit as many locations as supported by the tour.
  • A combination ticket that can be used to visit the “Statue of Liberty”, “Top of the Rock” and the “Empire Building”

Key Definitions

  • Merchant: The provider of the service (e.g. tour agency, operator, etc.)
  • Service: The service provided by the merchant (e.g. tour, activity, etc.).
  • Service Locations: The locations related to the service (e.g. the points of interest visited as part of the service, hotel pick-up, etc.).
    • Start/Meeting Location(s): The location where the service begins. You can also specify pick-up or meeting locations.
      • The start/meeting location(s) are displayed to users via custom intake forms (for selection), and to inform the users of the start/meeting location(s) on the UI.
    • Visited Location(s): The locations that are critical or closely related to the service
      • The visited location(s) are used to determine where the service will show up on various Google surfaces. There is no guarantee the POI of the visited location will show the service.
    • End Location: The location where the service ends.

All locations are used to improve the UI on the detailed activity pages (e.g. map pins, indication of location opening hours, etc.)

Adding Service Locations

Service Feed

In the service feed, specify service locations (if applicable). To do this, set the new Location field. This is a repeated field, so you can set multiple locations.

// Geographic information about a location.
message Location {
  // The Place ID for a place in the Google Places database and on Google Maps.
  // See for more about Place IDs.
  // If this is provided, Google will match the location to this place. (optional)
  string place_id = 1;

  // The location's name, telephone, url and geo are used to support matching
  // the location with places already present on Google Maps. It is recommended
  // to provide the location name if possible. (optional)
  // The name of the location. (optional)
  string name = 2;

  // The public telephone number of the location including its country and area
  // codes, e.g. +14567891234. (optional)
  string telephone = 3;

  // The url of the location's public website. (optional)
  string url = 4;

  // The Geo info of the location, including latitude, longitude, and address.
  // (optional)
  GeoCoordinates geo = 5;

  // Optional text to provide more precise description of the location, or
  // instructions assisting locating the place. E.g. "Front entrance of the
  // library", "meet at the intersect of Road A and Street B". (optional)
  Text description = 6;

  // The type of the location, must be supplied if this location is provided for
  // a Service.
  LocationType location_type = 7;

  // Unique reference of the location within the service. This id can be used to
  // refer to this location in other service fields. E.g in the custom intake
  // form, a set of location ids can be used to specify pick up location
  // options. If set, this id should be unique within the same service.
  // (optional)
  string location_id = 8;

enum LocationType {
  // Location type unspecified.
  // The location where this service visits.
  // The location where this service starts, also serves as MEETING_LOCATION/START_LOCATION.
  // The location where this service ends.
  • Optionally, set specific instructions of the location using description (e.g. Meet at the front desk of Hotel A)

  • If using custom intake forms (e.g. user can select from a list of hotel pick-up locations), set location_id.

Adding Hotel Pick-up

Service Feed

If your service supports hotel pick-up from multiple locations, you can implement this feature in the service feed.

  • Set a service location with location_id set
  • Set intake_form and add the location_id to it

Example Hotel pick-up Service Feed

  "location": [
      "name": "Hilton Hawaiian Village Waikiki Beach Resort",
      "geo": {
        "latitude": 21.283949,
        "longitude": -157.836151,
        "unstructured_address": "2005 Kalia Road Honolulu, Hawaii 96815 United States"
      "location_type": "START_LOCATION",
      "location_id": "hotel-1"
      "name": "Fairmont Orchid - Hawaii",
      "geo": {
        "latitude": 19.950553,
        "longitude": -155.859931,
        "unstructured_address": "1 North Kaniku Drive Kohala Coast, Waimea Hawaii 96743 United States"
      "location_type": "START_LOCATION",
      "location_id": "hotel-2"
      "name": "Manago Hotel Restaurant",
      "geo": {
        "latitude": 19.489207,
        "longitude": -155.910936,
        "unstructured_address": "82-6155 Mamalahoa Highway Captain Cook, Hawaii 96704 United States"
      "location_type": "START_LOCATION",
      "location_id": "hotel-3"
  "intake_form": {
    "field": [
        "type": "LOCATION_SEARCH",
        "label": "Please select the pick up hotel below:",
        "value": [
        "is_required": true,
        "id": "hotel-pick-up-form-1"

If the location_id in the intake_form is not found in the list of service locations, the field will not show up in the form.


When the user buys the tickets, the CreateOrderResponse should return the responses the user filled out in the custom intake form.

// User's answers to merchant questions.
message IntakeFormAnswers {
  repeated IntakeFormFieldAnswer answer = 1;

message IntakeFormFieldAnswer {
  // This id should be the same as the id of the corresponding question.
  string id = 1;

  // The response given by the user.
  // One string ("true" or "false") for BOOLEAN
  // One or more strings for CHECKBOXES.
  // For LOCATION_SEARCH, the response could be:
  //   1. Matches one of the "location_id" in the "location" field in the
  //   service feed.
  //   2. User input answer containing location information that are not
  //   provided in the feed.
  repeated string response = 2;

Example Hotel pick-up CreateOrderResponse

  "order": {
    "order_id": "order-1",
    "merchant_id": "100001",
    "item": [
        "service_id": "1000",
        "start_sec": "1546647234",
        "duration_sec": 3600,
        "tickets": [
            "ticket_id": "ticket-1",
            "count": 1
        "price": {
          "price_micros": 100000000,
          "currency_code": "USD"
        "status": "CONFIRMED",
        "intake_form_answers": {
          "answer": [
              "id": "hotel-pick-up-form-1",
              "response": "hotel-1"
    "user_information": {
      "email": "",
      "family_name": "John",
      "given_name": "Smith",
      "telephone": "+1 800-123-4567",
      "user_id": "2017492857928759285"
  "payment_processing_parameters": {
  "idempotency_token": "1239874"

The response field should be used to indicate the location_id the user selected or a custom location for pick-up if the pick-up address is not found in the provided locations.