Was this helpful?

Adding Locations to Itineraries

Using GraphQL, you can locations to your itinerary. Alpaca will organise the locations you add for itineraries into various structures, including a simple list through to something more complex (such as organised by segments etc).

You may also wish to review the following guides as starting points:

Prerequisites

_
  • You'll need an itinerary you want to add to and locate the Itinerary ID
  • The itinerary will need to be unassigned to a profile, or you'll need your private API Key

Adding Locations to an Itinerary

Locations added to an itinerary contain information for the audience such as the physical place they are visiting, as well as any personalised content or planning data about that location (such as stories/photos or supplying reasons to visit the place).

When we add locations to an itinerary, we will need to have the itinerary id that we will be adding to.

Adding a Location Directly to an Itinerary

When you want to add a location to your itinerary that does not have an associated place provider, you can add the location directly to the itinerary. In this case, you need to provide the title and longitude and latitude of the location to the createItineraryLocation mutation.

Here is an example of how you can add a location directly to an itinerary:

1mutation {
2  createItineraryLocation(
3    itineraryId: "itinerary/ABC123"
4    location: {
5      title: "Eiffel Tower"
6      synopsis: "An iconic place of interest"
7      place: { position: { lon: 2.2944, lat: 48.8584 } }
8    }
9  ) {
10    location {
11      id
12    }
13  }
14}

Sandbox: Configure | Try Operation

In the above example, we are adding the location "Eiffel Tower" to the itinerary with the ID "itinerary/ABC123". The longitude and latitude of the location is provided in the position field of the place object.

If the mutation is successful, the server will return the ID of the newly created location, as seen in the location field of the response.

1{
2  "data": {
3    "createItineraryLocation": {
4      "location": {
5        "__typename": "ItineraryLocation",
6        "id": "itinerary/ABC123/location/DEF456"
7      }
8    }
9  }
10}

Various information about the location can be stored against the location.

It is important to note that when adding a location directly, you will not have access to additional information about the location from a place provider. If you want to add a location with more information, you can use a place provider as described in the next subsection.

Adding a Location using a Place provider

When adding a location to your itinerary, you have the option to associate the location with a place provider. This allows you to access additional information about the location, such as photos, ratings, contact information, addresses, website and social URL's or other information that is available from the place provider.

Alpaca supports a number of place providers, including OpenStreetMap/WikiData, GeoNames, OpenAddresses, Facebook, and Australian Tourism Data Warehouse. Each provider has their own unique identifier format for a place, so make sure to use the correct format when creating a location.

For example, to add a location to your itinerary and associate it with a place on Facebook, you can use the following mutation:

1mutation CreateItineraryLocationWithFacebookPlace {
2  createItineraryLocation(
3    itineraryId: "itinerary/ABC123"
4    location: {
5      title: "Visit Mavis The Grocer"
6      synopsis: "A great place to grab a breakfast and a coffee"
7      place: {
8        id: "place/facebook:page:mavisthegrocer"
9        position: { lon: 145.0043, lat: -37.8021 }
10      }
11    }
12  ) {
13    location {
14      __typename
15      id
16    }
17  }
18}

Sandbox: Configure | Try Operation

In this example, we are using the Facebook place ID "place/facebook:page:mavisthegrocer" and providing a fallback position of lon: 145.0043, lat: -37.8021. When querying the itinerary, the position from the place provider will be used if available.

It's also worth noting that you can leave the place.id field empty, and instead you'll need to supply all the information about the place directly.

Using a place provider can be especially useful when you want to show additional information about the location, such as photos, ratings, or contact information, to your users. It also allows you to easily update the information about the location in case the place provider updates their data.

Storing your own References

In addition to linking locations to places provided by external providers, you may also want to store your own ID's against a location in your itinerary. To do this, you can use the special custom attributes custom/external-ref and custom/external-source.

The custom/external-ref attribute accepts a string value, which should be a unique identifier per record. The custom/external-source attribute is used to attribute the identifiers to a source. This attribute should be common across all your locations and differentiate between different source locations you may have.

Here's an example of creating an itinerary location with external references:

1mutation CreateItineraryLocationWithExternalReferences {
2  createItineraryLocation(
3    itineraryId: "itinerary/ABC123"
4    location: {
5      title: "Eiffel Tower"
6      place: { position: { lon: 2.2944, lat: 48.8584 } }
7      attrs: [
8        # Use the special custom attributes for linking to your identifiers
9        { id: "custom/external-ref", value: "12345" }
10        { id: "custom/external-source", value: "site" }
11      ]
12      # Other extended fields can be stored against a location
13      websiteUrl: "https://mywebsite.com/places/eiffel-tower"
14    }
15  ) {
16    location {
17      id
18
19      externalRef: attrValue(id: "custom/external-ref")
20      externalSource: attrValue(id: "custom/external-source")
21
22      websiteUrl
23    }
24  }
25}

Sandbox: Configure | Try Operation

With this example, the Alpaca platform will return the external reference ID's that you can then use to map your own place information outside of the Alpaca Travel GraphQL API call.

The Alpaca Data Structure enables a wide range of predefined fields for you to provide and store with your location. You can also store extended data outside of this set.

See More

Add to a specific position within the Itinerary

When adding an Itinerary Location to an itinerary, the createItineraryLocation mutation supports specifying where you wish to add the location.

In order to control the position, the fields "positionAtStart", "positionAtEnd", "positionAfterSibling", "positionBeforeSibling" and "positionOnLastCollection" fields are provided for you to specify the desired position for the added location.

1mutation {
2  createItineraryLocation(
3    itineraryId: "itinerary/ABC123"
4    location: {
5      title: "Eiffel Tower"
6      place: { position: { lon: 2.2944, lat: 48.8584 } }
7      # Specify the desired position to add the location
8      positionAfterSibling: { siblingId: "itinerary/ABC123/location/DEF456" }
9    }
10  ) {
11    location {
12      id
13    }
14  }
15}

Sandbox: Configure | Try Operation

In the above query, the positionAfterSibling property allows you to specify the siblingId to another existing location that you wish to insert the new location positioned after.

Retrieving Locations

Using the Alpaca GraphQL API, there are many different ways to query and retrieve the locations of the itinerary. This is typically done using either the node or itinerary query depending if you want to read back multiple locations at once, or want to target a specific location node.

The below example shows how to use the node query to retrieve a specific location based on an id.

1query GetItineraryLocation {
2  # The node query can generally target any ID
3  node(id: "itinerary/ABC123/location/DEF456") {
4    id
5    __typename
6
7    ... on ItineraryLocation {
8      # We can query the itinerary location fields specifically
9      title
10      synopsis
11
12      # Access the position and any information relating to this position
13      position {
14        lon
15        lat
16        # Use position attributes to query information, available without
17        # a place provider (relies on lon/lat positions)
18        # Access the timezone at the coordinate
19        timezone: attrValue(id: "place/time-zone")
20        # Access the currency for the country
21        currency: attrValue(id: "place/country-currency")
22        # Further information, such as regions..
23        iso3166: attrValue(id: "place/iso-3166-2")
24      }
25
26      # Use any additional attributes you have stored, such as your own ID's
27      externalRef: attrValue(id: "custom/external-ref")
28
29      place {
30        # When using a place provider, information can be accessed here
31        id
32        name
33
34        address {
35          addressLineOne
36          locality
37          region
38          country
39        }
40
41        # Extended place attributes
42        phoneNumber: attrValue(id: "place/phone-number")
43        websiteUrl: attrValue(id: "place/website-url")
44        facebookUrl: attrValue(id: "place/facebook-url")
45        instagramUrl: attrValue(id: "place/instagram-url")
46      }
47    }
48  }
49}

Sandbox: Configure | Try Operation

When adding a location to an itinerary without using a place provider, you will not have access to additional information such as the place's name, address, photos, or reviews. However, you can still add additional information to the location by including position attributes, which provide additional information about the longitude/latitude pair, such as the country, timezone, region, or currency used. Additionally, when querying places within Australia, additional geographical information from ABS and Wine Australia are provided. This can be useful if you have your own place data and wish to map it to an itinerary location.

See More

Managing Content

The Itinerary Location object provides predetermined fields for you to store your content and media associated with a location.

  • Title
  • Synopsis and Descriptions
  • Tags, Read More URL and Website URLs
  • Media (Contained in a seperate guide)
  • Attributes

You can provide this content when you are initially creating the location using the createItineraryLocation mutation, or alternatively use the updateItineraryLocation mutation to provide or update these values later.

1mutation CreateItineraryLocationWithContent {
2  createItineraryLocation(
3    itineraryId: "itinerary/ABC123"
4    location: {
5      place: { position: { lon: 2.2944, lat: 48.8584 } }
6      # Various standard fields, see "CreateItineraryLocationInput" type
7      title: "Eiffel Tower"
8      synopsis: "A short summary for the location"
9      description: "Markdown formatted description for the location"
10      # Extended attributes
11      attrs: [
12        { id: "place/website-url", value: "https://www.toureiffel.paris/en" }
13        {
14          id: "place/facebook-url"
15          value: "https://www.facebook.com/EiffelTower.OfficialPage"
16        }
17      ]
18    }
19  ) {
20    location {
21      id
22    }
23  }
24}

Sandbox: Configure | Try Operation

You can also update values using the "updateItineraryLocation" mutation.

1mutation UpdateItineraryLocationWithContent {
2  updateItineraryLocation(
3    id: "itinerary/ABC123/location/DEF456"
4    location: {
5      # Various standard fields, see "UpdateItineraryLocationInput" type
6      title: "Eiffel Tower"
7      synopsis: "A short summary for the location"
8      description: "Markdown formatted description for the location"
9      # Extended attributes
10      upsertAttrs: [
11        { id: "place/website-url", value: "https://www.toureiffel.paris/en" }
12        {
13          id: "place/facebook-url"
14          value: "https://www.facebook.com/EiffelTower.OfficialPage"
15        }
16      ]
17      # You can remove values using the deleteAttrs
18      # example value: [{ id: "place/website-url" }]
19      deleteAttrs: []
20    }
21  ) {
22    location {
23      id
24    }
25  }
26}

Sandbox: Configure | Try Operation

Formatting Descriptions

The description field is formatted using basic markdown formatting.

Common Attributes

You can also assign place attributes to the attributes within the location. You can not specifically assign the attributes to the place object, as the place object represents the dynamically references values from place providers, even if you are not using them.

AttributeDescription
place/addressThe address object to use for the place ("addressLineOne", "locality", "region", "country", etc)
place/phone-numberThe phone number to use for the place
place/website-urlThe website URL to use for the place
place/booking-urlThe booking URL to use for the place
place/facebook-urlThe facebook URL to use for the place
place/instagram-urlThe instagram URL to use for the place
place/opening-hoursThe opening hours of the place, stored in OSM Opening Hours format (See Accessing hours)

Checking if a place is present

Once you have added locations to your list, you may want to check if a particular place is already present in the list before adding it again. This can be useful for creating a "Add to List" button with different states, such as "Added" or "Remove" depending on whether the place is already present in the list.

The following GraphQL query can be used to check if a place is present in a list:

1query CheckItineraryPlacePresent {
2  itinerary(id: "itinerary/ABC123") {
3    descendants(placeIds: ["place/123"], first: 1) {
4      nodes {
5        id
6      }
7      totalCount
8    }
9  }
10}

Sandbox: Configure | Try Operation

The itinerary query is used, supplying the id of the list to check. The descendants field is then queried, providing the placeIds to check and the first parameter, which limits the number of returned results to 1.

In the response, the nodes field will contain an array of itinerary location objects, each representing a location in the list that matches the provided placeIds. The id field of each itinerary location object can be used to refer to the location in future operations. The totalCount field will indicate the total number of matching locations in the list, which can be used to check if the place is already present in the list.

Example response:

1{
2  "data": {
3    "itinerary": {
4      "descendants": {
5        "nodes": [
6          {
7            "id": "itineraryLocation/123"
8          }
9        ],
10        "totalCount": 1
11      }
12    }
13  }
14}

If the place is already present in the list, the totalCount field will be greater than 0.

Using multiple positions

The Location can also contain other positions that can assist with presenting the location to the user.

For instance, for a place, your place provider may provide a position in order to draw a pin or draw a label. This position is not the location we wish to send the user to when actually visiting this location physically.

Further to the example, you may also wish to have the user first navigate to a position such as a car park or entry gates.

This leads to the possibility of many different positions being used to describe the location being added.

You can assign a preferred position using the location.position or add an attribute to the location with the ID of itinerary/location/directions-position-preference

We also support the use custom data to contain further positions that you wish to store and leverage in you use case.

Reordering a location

A specific topic exists to assist you with reordering locations.

Removing a location

1# Removes an itinerary item, such as a location
2
3mutation DeleteItineraryLocation {
4  # Use the deleteItineraryItem operation to remove an itinerary location
5  deleteItineraryItem(
6    # Supply your ID of the itinerary location to remove (no undo)
7    id: "itinerary/ABC123/item/DEF456"
8  ) {
9    # Select back the ID of the itinerary location that was removed
10    id
11  }
12}

Sandbox: Configure | Try Operation

alpaca.tech

Copyright © 2024 - Made with love ❤️ in Australia.