Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Add deep links for iOS, Android, and web apps #25

Merged
merged 9 commits into from
Dec 5, 2019
144 changes: 144 additions & 0 deletions gbfs.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ This document explains the types of files and data that comprise the General Bik
* [system_regions.json](#system_regionsjson)
* [system_pricing_plans.json](#system_pricing_plansjson)
* [system_alerts.json](#system_alertsjson)
* [Deep Links - Analytics and Examples](#Deep-Links)
* [Possible Future Enhancements](#possible-future-enhancements)

## Revision History
Expand Down Expand Up @@ -54,6 +55,7 @@ system_alerts.json | Optional | Describes current system
* All files should be valid JSON
* All data should be UTF-8 encoded
* Line breaks should be represented by unix newline characters only (\n)
* All URIs must be a fully qualified URI that includes the scheme (e.g., http:// or https://), and any special characters in the URI must be correctly escaped. See http://www.w3.org/Addressing/URL/4_URI_Recommentations.html for a description of how to create fully qualified URI values.

### File Distribution
* This specification does not dictate the implementation details around the distribution of the JSON data files
Expand Down Expand Up @@ -172,6 +174,13 @@ phone_number | Optional | A single voice telephone number for the specifie
email | Optional | A single contact email address for customers to address questions about the system
timezone | Yes | The time zone where the system is located. Time zone names never contain the space character but may contain an underscore. Please refer to the "TZ" value in https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for a list of valid values
license_url | Optional | A fully qualified URL of a page that defines the license terms for the GBFS data for this system, as well as any other license terms the system would like to define (including the use of corporate trademarks, etc)
rental_apps | Optional | A JSON object that contains rental app information in the android and ios JSON objects.
\- android | Optional | A JSON object that contains rental app download and app discovery information for the Android platform in the store_uri and discovery_uri fields. See [examples](#Examples) of how to use these fields and [supported analytics](#Analytics).
&emsp;- store_uri | Conditionally Required | A URI where the rental Android app can be downloaded from. Typically this will be a URI to an app store such as Google Play. If the URI points to an app store such as Google Play, the URI should follow Android best practices so the viewing app can directly open the URI to the native app store app instead of a website. <br><br> If a rental_uris.android field is populated then this field is required, otherwise it is optional. <br><br>See the [Analytics](#Analytics) section for how viewing apps can report the origin of the deep link to rental apps. <br><br>Example value: `https://play.google.com/store/apps/details?id=com.abcrental.android`
&emsp;- discovery_uri | Conditionally Required | A URI that can be used to discover if the rental Android app is installed on the device (e.g., using [`PackageManager.queryIntentActivities()`](https://developer.android.com/reference/android/content/pm/PackageManager.html#queryIntentActivities)). This intent is used by viewing apps prioritize rental apps for a particular user based on whether they already have a particular rental app installed. <br><br>This field is required if a rental_uris.android field is populated, otherwise it is optional. <br><br>Example value: `com.abcrental.android://`
\- ios | Optional | A JSON object that contains rental information for the iOS platform in the store_uri and discovery_uri fields. See [examples](#Examples) of how to use these fields and [supported analytics](#Analytics).
&emsp;- store_uri | Conditionally Required | A URI where the rental iOS app can be downloaded from. Typically this will be a URI to an app store such as the Apple App Store. If the URI points to an app store such as the Apple App Store, the URI should follow iOS best practices so the viewing app can directly open the URI to the native app store app instead of a website. <br><br>If a rental_uris.ios field is populated then this field is required, otherwise it is optional. <br><br>See the [Analytics](#Analytics) section for how viewing apps can report the origin of the deep link to rental apps. <br><br>Example value: `https://apps.apple.com/app/apple-store/id123456789`
&emsp;- discovery_uri | Conditionally Required | A URI that can be used to discover if the rental iOS app is installed on the device (e.g., using [`UIApplication canOpenURL:`](https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl?language=objc)). This intent is used by viewing apps prioritize rental apps for a particular user based on whether they already have a particular rental app installed. <br><br>This field is required if a rental_uris.ios field is populated, otherwise it is optional. <br><br>Example value: `com.abcrental.ios://`


### station_information.json
Expand All @@ -191,6 +200,10 @@ stations | Yes | Array that contains one object per station in th
\- post_code | Optional | Postal code where station is located
\- rental_methods | Optional | Array of enumerables containing the payment methods accepted at this station. <br />Current valid values (in CAPS) are:<br /><ul><li>KEY _(i.e. operator issued bike key / fob / card)_</li> <li>CREDITCARD</li> <li>PAYPASS</li> <li>APPLEPAY</li> <li>ANDROIDPAY</li> <li>TRANSITCARD</li> <li>ACCOUNTNUMBER</li> <li>PHONE</li> </ul> This list is intended to be as comprehensive at the time of publication as possible but is subject to change, as defined in [File Requirements](#file-requirements) above
\- capacity | Optional | Number of total docking points installed at this station, both available and unavailable
rental_uris | Optional | A JSON object that contains rental URIs for Android, iOS, and web in the android, ios, and web fields. See [examples](#Examples) of how to use these fields and [supported analytics](#Analytics).
\- android | Optional | The URI that can be passed to an Android app with an `android.intent.action.VIEW` Android intent to support Android Deep Links (https://developer.android.com/training/app-links/deep-linking). Please use Android App Links (https://developer.android.com/training/app-links) if possible so viewing apps don’t need to manually manage the redirect of the user to the app store if the user doesn’t have the application installed. <br><br>This URI should be a deep link specific to this station, and should not be a general rental page that includes information for more than one station. The deep link should take users directly to this station, without any prompts, interstitial pages, or logins. Make sure that users can see this station even if they never previously opened the application. This is the same principle as the ["first click free"](https://support.google.com/news/publisher/answer/40543) experience for web sites. <br><br>If this field is empty, it means deep linking isn’t supported in the native Android rental app. <br><br>Note that URIs do not necessarily include the station_id for this station - other identifiers can be used by the rental app within the URI to uniquely identify this station. <br><br>See the [Analytics](#Analytics) section for how viewing apps can report the origin of the deep link to rental apps. <br><br>Android App Links example value: `https://www.abc.com/app?sid=1234567890&platform=android` <br><br>Deep Link (without App Links) example value: `com.abcrental.android://open.abc.app/app?sid=1234567890`
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lyft has some concerns with the "First Click Free" language - this would require some major re-architecture of our apps (I'm sure other providers would have similar issues) and isn't a super common scenario. This is currently marked as "should" - we will not be requiring providers to do this, correct?

For what it's worth Google has since moved away from requiring FCF.

\- ios | Optional | The URI that can be used on iOS to launch the rental app for this station. More information on this iOS feature can be found [here](https://developer.apple.com/documentation/uikit/core_app/allowing_apps_and_websites_to_link_to_your_content/communicating_with_other_apps_using_custom_urls?language=objc). Please use iOS Universal Links (https://developer.apple.com/ios/universal-links/) if possible so viewing apps don’t need to manually manage the redirect of the user to the app store if the user doesn’t have the application installed. <br><br>This URI should be a deep link specific to this station, and should not be a general rental page that includes information for more than one station. The deep link should take users directly to this station, without any prompts, interstitial pages, or logins. Make sure that users can see this station even if they never previously opened the application. This is the same principle as the ["first click free"](https://support.google.com/news/publisher/answer/40543) experience for web sites. <br><br>If this field is empty, it means deep linking isn’t supported in the native iOS rental app. <br><br>Note that the URI does not necessarily include the station_id - other identifiers can be used by the rental app within the URL to uniquely identify this station. <br><br>See the [Analytics](#Analytics) section for how viewing apps can report the origin of the deep link to rental apps. <br><br>iOS Universal Links example value: `https://www.abc.com/app?sid=1234567890&platform=ios` <br><br>Deep Link (without Universal Links) example value: `com.abcrental.ios://open.abc.app/app?sid=1234567890`
\- web | Optional | A URL that can be used by a web browser to show more information about renting a vehicle at this station. <br><br>This URL should be a deep link specific to this station, and should not be a general rental page that includes information for more than one station. The deep link should take users directly to this station, without any prompts, interstitial pages, or logins. Make sure that users can see this station even if they never previously opened the application. This URI should follow ["first click free"](https://support.google.com/news/publisher/answer/40543) experience for web sites. <br><br>If this field is empty, it means deep linking isn’t supported for web browsers. <br><br>Example value: https://www.abc.com/app?sid=1234567890

### station_status.json

Expand Down Expand Up @@ -218,6 +231,10 @@ bikes | Yes | Array that contains one object per bike that is
\- lon | Yes | Longitude of the bike. The field value must be a valid WGS 84 latitude in decimal degrees format. See: http://en.wikipedia.org/wiki/World_Geodetic_System, https://en.wikipedia.org/wiki/Decimal_degrees
\- is_reserved | Yes | 1/0 value - is the bike currently reserved for someone else
\- is_disabled | Yes | 1/0 value - is the bike currently disabled (broken)
rental_uris | Optional | A JSON object that contains rental URIs for Android, iOS, and web in the android, ios, and web fields. See [examples](#Examples) of how to use these fields and [supported analytics](#Analytics).
\- android | Optional | The URI that can be passed to an Android app with an android.intent.action.VIEW Android intent to support Android Deep Links (https://developer.android.com/training/app-links/deep-linking). Please use Android App Links (https://developer.android.com/training/app-links) if possible so viewing apps don’t need to manually manage the redirect of the user to the app store if the user doesn’t have the application installed. <br><br>This URI should be a deep link specific to this bike, and should not be a general rental page that includes information for more than one bike. The deep link should take users directly to this bike, without any prompts, interstitial pages, or logins. Make sure that users can see this bike even if they never previously opened the application. This is the same principle as the ["first click free"](https://support.google.com/news/publisher/answer/40543) experience for web sites. <br><br>If this field is empty, it means deep linking isn’t supported in the native Android rental app. <br><br>Note that URIs do not necessarily include the bike_id for this bike - other identifiers can be used by the rental app within the URI to uniquely identify this bike. <br><br>See the [Analytics](#Analytics) section for how viewing apps can report the origin of the deep link to rental apps. <br><br>Android App Links example value: `https://www.abc.com/app?sid=1234567890&platform=android` <br><br>Deep Link (without App Links) example value: `com.abcrental.android://open.abc.app/app?sid=1234567890`
\- ios | Optional | The URI that can be used on iOS to launch the rental app for this bike. More information on this iOS feature can be found here: https://developer.apple.com/documentation/uikit/core_app/allowing_apps_and_websites_to_link_to_your_content/communicating_with_other_apps_using_custom_urls?language=objc. Please use iOS Universal Links (https://developer.apple.com/ios/universal-links/) if possible so viewing apps don’t need to manually manage the redirect of the user to the app store if the user doesn’t have the application installed. <br><br>This URI should be a deep link specific to this bike, and should not be a general rental page that includes information for more than one bike. The deep link should take users directly to this bike, without any prompts, interstitial pages, or logins. Make sure that users can see this bike even if they never previously opened the application. This is the same principle as the ["first click free"](https://support.google.com/news/publisher/answer/40543) experience for web sites. <br><br>If this field is empty, it means deep linking isn’t supported in the native iOS rental app. <br><br>Note that the URI does not necessarily include the bike_id - other identifiers can be used by the rental app within the URL to uniquely identify this bike. <br><br>See the [Analytics](#Analytics) section for how viewing apps can report the origin of the deep link to rental apps. <br><br>iOS Universal Links example value: `https://www.abc.com/app?sid=1234567890&platform=ios` <br><br>Deep Link (without Universal Links) example value: `com.abcrental.ios://open.abc.app/app?sid=1234567890`
\- web | Optional | A URL that can be used by a web browser to show more information about renting a vehicle at this bike. <br><br>This URL should be a deep link specific to this bike, and should not be a general rental page that includes information for more than one bike. The deep link should take users directly to this bike, without any prompts, interstitial pages, or logins. Make sure that users can see this bike even if they never previously opened the application. This URI should follow ["first click free"](https://support.google.com/news/publisher/answer/40543) experience for web sites. <br><br>If this field is empty, it means deep linking isn’t supported for web browsers. <br><br>Example value: https://www.abc.com/app?sid=1234567890

### system_hours.json
Describes the system hours of operation. A JSON array of hours defined as follows:
Expand Down Expand Up @@ -317,6 +334,133 @@ alerts | Yes | Array - alert objects each indicating a separa
\- description | Optional | String - Detailed text description of the alert
\- last_updated | Optional | Integer POSIX timestamp indicating the last time the info for the particular alert was updated

## Deep Links

Deep links to iOS, Android, and web apps are supported via URIs in the `system_information.json`, `station_information.json`, and `free_bike_status.json` files. The following sections describe how analytics can be added to these URIs, as well as some examples.

### Analytics

In all of the rental URI fields, a viewing app can report the origin of a deep link to request to a rental app by appending the `client_id` parameter to the URI along with the domain name for the viewing app.

For example, if Google is the viewing app, it can append:

`client_id=google.com`

...to the URI field to report that Google is the originator of the deep link request. If the Android URI is:

`com.abcrental.android://open.abc.app/stations?id=1234567890`

...then the URI used by Google would be: `com.abcrental.android://open.abc.app/stations?id=1234567890&client_id=google.com`

Other supported parameters include:

1. `ad_id` - Advertising ID issued to the viewing app (e.g., IFDA on iOS)
2. `token` - A token identifier that was issued by the rental app to the viewing app.

### Examples

#### Example 1 - App Links on Android and Universal Links on iOS are supported:

*system_information.json*

```
{
"last_updated": 1572447999,
"data": {
"system_id": "1000",
"short_name": "ABC Bike Rental",
"rental_apps": {
"android": {
"discovery_uri": "com.abcrental.android://"
},
"ios": {
"discovery_uri": "com.abcrental.ios://"
}
}
...
```

*station_information.json*

```
"stations":[
{
"station_id":425,
"name":"Coppertail",
"lat":27.9563335328521,
"lon":-82.430436084371,
"rental_uris": {
"android":"https://www.abc.com/app?sid=1234567890&platform=android",
"ios":"https://www.abc.com/app?sid=1234567890&platform=ios"
}
},
...
```


Note that the Android URI and iOS Universal Link URLs don’t necessarily use the same identifier as the station_id.


#### Example 2 - App Links are not supported on Android and Universal Links are not supported on iOS, but deep links are still supported on Android and iOS:

*system_information.json*

```
{
"last_updated": 1572447999,
"data": {
"system_id": "1000",
"short_name": "ABC Bike Rental",
"rental_apps": {
"android": {
"discovery_uri": "com.abcrental.android://"
"store_uri": "https://play.google.com/store/apps/details?id=com.abcrental.android",
},
"ios": {
"store_uri": "https://apps.apple.com/app/apple-store/id123456789",
"discovery_uri": "com.abcrental.ios://"
}
}

...
```

*station_information.json*


```
"stations":[
{
"station_id":425,
"name":"Coppertail",
"lat":27.9563335328521,
"lon":-82.430436084371,
"rental_uris": {
"android":"com.abcrental.android://open.abc.app/app?sid=1234567890",
"ios":"com.abcrental.ios://open.abc.app/app?sid=1234567890"
}
},
...
```

#### Example 3 - Deep link web URLs are supported, but not Android or iOS native apps:

*station_information.json*

```
"stations":[
{
"station_id":425,
"name":"Coppertail",
"lat":27.9563335328521,
"lon":-82.430436084371,
"rental_uris": {
"web":"https://www.abc.com/app?sid=1234567890",
}
},
...
```

## Possible Future Enhancements
There are some items that were proposed in an earlier version of this document but which do not fit into the current specification. They are collected here for reference and for possible discussion and inclusion in this or a future version.

Expand Down