Overview
Google Maps Platform is available for web (JS, TS), Android, and iOS, and also offers web services APIs for getting information about places, directions, and distances. The samples in this guide are written for one platform, but documentation links are provided for implementation on other platforms.
Quick Builder in the Google Cloud Console lets you build address form autocompletion using an interactive UI that generates JavaScript code for you.
Users have become accustomed to living and operating in a digital world in which convenience, speed, and security are baseline expectations. When they apply for something such as a credit card, bank account or loan, they expect the process to be fast and easy.
The more users have to type or enter duplicate data, the less chance you have at retaining them as customers. Creating a quick, easy and verified sign-up experience will improve the user experience while giving you a leg up in keeping users on your site.
Manually entered addresses can lead to lowered conversions, erroneous CRM data, and costly delivery mistakes. Quick & Verified Sign-up makes sign-up faster, instantly suggesting nearby addresses with just a few thumb taps and displaying the inputted address for visual confirmation, helping the user feel confident that they’ve entered the correct address. Verifying the user’s address using their current location also helps fraud prevention and strengthens user confidence in your products and services. Verification can also increase your confidence in providing virtual bank and credit cards instantly.
This topic provides implementation guidance for building a Quick & Verified Sign-up experience with Google Maps Platform. Since users will most likely sign up on mobile devices, most of the implementation examples in this topic focus on Android. (You can see the full sample source here). You can also use the iOS SDKs to accomplish the same things.
The following diagram shows the core APIs involved in building the solution (click to enlarge).
Enabling APIs
To implement these recommendations, you must enable the following APIs in the Google Cloud Console:
- Maps SDK for Android (or the API for your platform of choice)
- Places API
- Geocoding API
For more information about setup, see Getting started with Google Maps Platform.
Best practices sections
Following are the practices and customizations we'll cover in this topic.
- The check mark icon is a core best practice.
- The star icon is an optional but recommended customization to enhance the solution.
Adding autocomplete to input fields | Autofill an address form. Add type-as-you-go functionality to improve the user experience on all platforms and improve address accuracy with minimum keystrokes. | |
Providing visual confirmation of the address | Let users see their address on a map as a visual confirmation that they entered the correct address. | |
Comparing user-entered address to device location | Compare the user's selected or entered address with their current device location to help determine that they are at the indicated address. (For this to work, users should be at home when they sign up.) | |
Tips to further enhance Quick & Verified Sign-up | You can enhance address entry even further with additions such as customizing the look and feel of the Autocomplete widget or letting users select the name of a business or landmark as an address. |
Adding autocomplete to input fields
This example uses: Places SDK for Android | Also available: iOS | JavaScript |
Place Autocomplete can simplify address entry in your application, leading to higher conversion rates and a seamless experience for your customers. Autocomplete provides a single, quick-entry field with "type-ahead" address prediction that can be used to automatically populate a sign-up address form. By incorporating the Place Autocomplete in your sign-up flow, you can:
- Reduce address entry errors.
- Decrease the number of steps in the sign-up process.
- Simplify the address entry experience on mobile or wearable devices.
- Significantly reduce keystrokes and total time required for a customer to sign up.
When the user selects the Autocomplete entry box and begins typing, a list of address predictions appear.
When the user selects an address from the list of predictions, you can use the response to verify the address and get the location. Your application can then populate the correct fields of the address entry form, as shown in the following figure.
Videos: Enhance address forms with Place Autocomplete
Address forms
Android
iOS
Web
Google Maps Platform provides a Place Autocomplete widget for mobile platforms and web. The widget, shown in the previous figures, provides a search dialog with built-in autocomplete functionality that you can even optimize for location-scoped search.
This section describes how to implement Place Autocomplete for Quick & Verified Sign-up.
Adding the Place Autocomplete widget
In Android, you can add the autocomplete widget using an Autocomplete intent that launches Place Autocomplete from the Address Line 1 input field, where the user will start entering their address. When they start typing, they'll be able to select their address from the list of Autocomplete predictions.
First, prepare an activity launcher, using
ActivityResultLauncher
,
that will listen for a result
from the launched activity. The result callback will contain a Place object
corresponding to the address that the user selects from Autocomplete
predictions.
private final ActivityResultLauncher<Intent> startAutocomplete = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK) { Intent intent = result.getData(); if (intent != null) { Place place = Autocomplete.getPlaceFromIntent(intent); // Write a method to read the address components from the Place // and populate the form with the address components Log.d(TAG, "Place: " + place.getAddressComponents()); fillInAddress(place); } } else if (result.getResultCode() == Activity.RESULT_CANCELED) { // The user canceled the operation. Log.i(TAG, "User canceled autocomplete"); } });
Next, define the fields, location, and type properties of the
Place Autocomplete intent and build it with
Autocomplete.IntentBuilder
.
Finally, launch the intent using the ActivityResultLauncher
defined in the
previous code sample.
private void startAutocompleteIntent() { // Set the fields to specify which types of place data to // return after the user has made a selection. List<Place.Field> fields = Arrays.asList(Place.Field.ADDRESS_COMPONENTS, Place.Field.LAT_LNG, Place.Field.VIEWPORT); // Build the autocomplete intent with field, country, and type filters applied Intent intent = new Autocomplete.IntentBuilder(AutocompleteActivityMode.OVERLAY, fields) .setCountries(Arrays.asList("US")) .setTypesFilter(new ArrayList<String>() {{ add(TypeFilter.ADDRESS.toString().toLowerCase()); }}) .build(this); startAutocomplete.launch(intent); }
Handling the address returned by Place Autocomplete
Defining the ActivityResultLauncher
earlier also defined what should be
done when the activity result is returned in the callback. If the user
selected a prediction, it will be delivered in the intent contained in
the result object. Since the intent was built by Autocomplete.IntentBuilder
,
the method Autocomplete.getPlaceFromIntent()
can extract the Place object
from it.
private final ActivityResultLauncher<Intent> startAutocomplete = registerForActivityResult( new ActivityResultContracts.StartActivityForResult(), result -> { if (result.getResultCode() == Activity.RESULT_OK) { Intent intent = result.getData(); if (intent != null) { Place place = Autocomplete.getPlaceFromIntent(intent); // Write a method to read the address components from the Place // and populate the form with the address components Log.d(TAG, "Place: " + place.getAddressComponents()); fillInAddress(place); } } else if (result.getResultCode() == Activity.RESULT_CANCELED) { // The user canceled the operation. Log.i(TAG, "User canceled autocomplete"); } });
From there, call Place.getAddressComponents()
and match each address
component to its corresponding input field in the address form, populating the
field with the value from the user's selected Place.
Capturing address data from the prediction instead of a manually entered address helps ensure address accuracy, ensures that the address is known and can be delivered to, and reduces user keystrokes.
Considerations when implementing Place Autocomplete
Place Autocomplete has a number of options that allow it to be flexible with its implementation if you want to use more than just the widget. You can use a combination of services to get exactly what you need to match a location in the correct way.
For an ADDRESS form, set the types parameter to
address
to restrict the matches to full street addresses. Learn more about types supported in Place Autocomplete requests.Set the appropriate restrictions and biases if you don’t need to search worldwide. There are a number of parameters that can be used to bias or restrict any match to only specific regions.
Use
RectangularBounds
to set the rectangular bounds to constrain for an area, usesetLocationRestriction()
to make sure only addresses in those areas are returned.Use
setCountries()
to restrict responses to a certain set of countries.
Leave fields editable in case certain fields are missed from the match, and allow customers to update the address if required. Since most addresses returned by Place Autocomplete do not contain subpremise numbers such as apartment, suite, or unit numbers, you can move the focus to Address Line 2 to encourage the user to fill in that information if necessary.
Providing visual confirmation of the address
This example uses: Maps SDK for Android | Also available: iOS | JavaScript |
As part of address entry, provide users with visual confirmation of the address on a map. This offers users additional assurance that the address is correct.
The following figure shows a map below the address with a pin at the address entered.
The following example follows the basic steps for adding a map in Android. Refer to the documentation for more details.
- Adding
SupportMapFragment
(in this case, adding a fragment dynamically) - Getting a handle to the fragment and registering the callback
- Styling and adding a marker to the map
- Disabling map controls
Adding SupportMapFragment
First, add a SupportMapFragment
fragment to the
layout XML file.
<fragment android:name="com.google.android.gms.maps.SupportMapFragment" android:id="@+id/confirmation_map" android:layout_width="match_parent" android:layout_height="match_parent"/>
Then, programmatically add the fragment if it doesn't exist yet.
private void showMap(Place place) { coordinates = place.getLatLng(); // It isn't possible to set a fragment's id programmatically so we set a tag instead and // search for it using that. mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentByTag(MAP_FRAGMENT_TAG); // We only create a fragment if it doesn't already exist. if (mapFragment == null) { mapPanel = ((ViewStub) findViewById(R.id.stub_map)).inflate(); GoogleMapOptions mapOptions = new GoogleMapOptions(); mapOptions.mapToolbarEnabled(false); // To programmatically add the map, we first create a SupportMapFragment. mapFragment = SupportMapFragment.newInstance(mapOptions); // Then we add it using a FragmentTransaction. getSupportFragmentManager() .beginTransaction() .add(R.id.confirmation_map, mapFragment, MAP_FRAGMENT_TAG) .commit(); mapFragment.getMapAsync(this); } else { updateMap(coordinates); } }
Getting a handle to the fragment and registering the callback
To get a handle to the fragment, call the
FragmentManager.findFragmentById
method and pass it the resource ID of the fragment in your layout file. If you added the fragment dynamically, skip this step because you already retrieved the handle.Call the
getMapAsync
method to set the callback on the fragment.
For example, if you added the fragment statically:
Kotlin
val mapFragment = supportFragmentManager .findFragmentById(R.id.map) as SupportMapFragment mapFragment.getMapAsync(this)
Java
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() .findFragmentById(R.id.map); mapFragment.getMapAsync(this);
Styling and adding a marker to the map
When the map is ready, set the style, center the camera, and add a marker at the coordinates of the entered address. The following code uses styling defined in a JSON object or you can alternatively load a map ID that has been defined with Cloud-based Maps Styling.
@Override public void onMapReady(@NonNull GoogleMap googleMap) { map = googleMap; try { // Customise the styling of the base map using a JSON object defined // in a string resource. boolean success = map.setMapStyle( MapStyleOptions.loadRawResourceStyle(this, R.raw.style_json)); if (!success) { Log.e(TAG, "Style parsing failed."); } } catch (Resources.NotFoundException e) { Log.e(TAG, "Can't find style. Error: ", e); } map.moveCamera(CameraUpdateFactory.newLatLngZoom(coordinates, 15f)); marker = map.addMarker(new MarkerOptions().position(coordinates)); }
Disabling map controls
To keep the map simple by showing location without additional map controls (such as compass, toolbar, or other built-in features), consider disabling the controls you don't find necessary. On Android, another option is to enable lite mode to provide limited interactivity.
Comparing user-entered address to device location
Obtaining proof of address—being confident that the user is at the address they entered—can be complicated by factors such as remote user location, users moving to a new address, or digital businesses (such as digital banks) that don't have a physical location that users can visit to provide proof of address with utility bills or other documentation. Providing digital ways to verify user addresses lets you provide a faster, frictionless sign-up experience.
Security is paramount in obtaining a check of address, especially with a digital sign-up process. This section provides guidance and samples for checking whether a user's location during sign-up matches the address they enter as their own.
The process for comparing an entered address to a device location involves the following steps:
- Converting the user-entered address to geographic coordinates.
- Prompting the user for permission to obtain their device's location.
- Calculating the distance between the entered address and device location. You get to determine the maximum distance that counts for an address-location match.
The following figure is an example of how you might prompt users to compare the address they entered to their current location.
Converting the user-entered address to geographic coordinates
This example uses: Places SDK for Android | Also available: iOS | JavaScript | Geocoding API |
After users agree to address verification (by touching "Verify I'm there now" in the previous figure), the first step in comparing address with current location is converting the entered address to geographic coordinates.
If the user selected their address with Place Autocomplete, be sure to request
Place.Field.LAT_LNG
in the Place Autocomplete field list as shown in the
Adding the Place Autocomplete widget code snippet, and call the
Place.getLatLng()
method to obtain the geographical coordinates of the selected address.
coordinates = place.getLatLng();
If the user manually entered their address or made edits after Place Autocomplete filled the fields, use the Android Geocoder service or the Geocoding API to look up the coordinates that correspond to that address.
Example
https://maps.googleapis.com/maps/api/geocode/json?address=1600%20Amphitheatre%2BParkway%2C%20Mountain%20View%2C%20CA%2094043&key=YOUR_API_KEY
Be sure to URL encode the call to the Geocoding API.
URL encoding quick reference: %20
= space, %2B
= + (plus), %2C
= , (comma)
Prompting the user for permission to obtain their device's location
To get the user's device location, you need to request user permission to enable location services. Using the guidance in the Android documentation on building location-aware apps, implement the following flow:
Request location permission, as a one-time grant, at a precise level (
ACCESS_FINE_LOCATION
).If the user grants location access, get the user location.
If the user rejects location access, handle the rejection gracefully. For example, you could present the following type of message (assuming you're not storing the user's current location):
"If you don't let the app know your precise location, you'll need to verify by mail to activate your account. [OK]"
The following figure shows an example prompt for users to allow permission to obtain the device location.
To check for location permission, prepare an activity launcher that will
listen for a result
from the launched activity with
ActivityResultLauncher
.
The result callback will contain a String indicating whether the user granted
or denied the requested permission.
// Register the permissions callback, which handles the user's response to the // system permissions dialog. Save the return value, an instance of // ActivityResultLauncher, as an instance variable. private final ActivityResultLauncher<String> requestPermissionLauncher = registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted -> { if (isGranted) { // Since ACCESS_FINE_LOCATION is the only permission in this sample, // run the location comparison task once permission is granted. // Otherwise, check which permission is granted. getAndCompareLocations(); } else { // Fallback behavior if user denies permission Log.d(TAG, "User denied permission"); } });
Then, check if the app already has ACCESS_FINE_LOCATION
permission.
If it doesn't, ask the user for it by launching the permission request
activity using the launcher defined in the preceding step.
private void checkLocationPermissions() { if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) { getAndCompareLocations(); } else { requestPermissionLauncher.launch( ACCESS_FINE_LOCATION); } }
Once the ACCESS_FINE_LOCATION
permission is granted, use the fused location
provider to get the last known location
of the device and create a LatLng
object from it.
FusedLocationProviderClient fusedLocationClient = LocationServices.getFusedLocationProviderClient(this); fusedLocationClient.getLastLocation() .addOnSuccessListener(this, location -> { // Got last known location. In some rare situations this can be null. if (location == null) { return; } deviceLocation = new LatLng(location.getLatitude(), location.getLongitude()); // ... }); }
Calculating the distance between the entered address and device location
Use math to calculate the distance between two latitude/longitude coordinates (entered address and device location). The open source Maps SDK for Android Utility Library has some handy methods to calculate the spherical distance between two points on Earth.
First, install the Maps SDK for Android Utility Library by adding the following
dependency to your app's build.gradle.kts
file:
dependencies { // Utility Library for Maps SDK for Android // You do not need to add a separate dependency for the Maps SDK for Android // since this library builds in the compatible version of the Maps SDK. implementation("com.google.maps.android:android-maps-utils:3.8.2") }
Then, back in the activity file after getting the last known device location, define a radius in meters to consider the two locations as "matched." The radius should be large enough to account for variability in GPS accuracy and the size of the place at the user's entered address. For example:
private static final double acceptableProximity = 150;
Then, use the utility library method computeDistanceBetween()
to calculate the distance between the device location and the user-entered
address location. If the distance falls within the radius defined above,
consider the locations matched.
// Use the computeDistanceBetween function in the Maps SDK for Android Utility Library // to use spherical geometry to compute the distance between two Lat/Lng points. double distanceInMeters = computeDistanceBetween(deviceLocation, enteredLocation); if (distanceInMeters <= acceptedProximity) { Log.d(TAG, "location matched"); // TODO: Display UI based on the locations matching } else { Log.d(TAG, "location not matched"); // TODO: Display UI based on the locations not matching }
If the address and location match, display a confirmation in the app, as shown in the following figure.
Tips to further enhance Quick & Verified Sign-up
Allow users to enter an address based on a business or point-of-interest
name. The "type ahead" prediction service not only works for addresses,
but you may also choose to let users enter business or landmark names.
To allow for both addresses and establishment names to be entered, remove
the types
property from the Autocomplete definition.
Customize the look and feel of the Place Autocomplete box to match your website style. If you prefer to control the look and feel of Place Autocomplete in your app rather than use Google's widget, you can use Place Autocomplete programmatically to power the UI you build with the Place Autocomplete service.