This section shows how to use the JavaScript fleet tracking library
to view a fleet. These procedures assume you have set up the fleet
tracking library and loaded a map. For details, see
[Set up the JavaScript fleet tracking library](https://developers.google.com/maps/documentation/mobility/operations/fleet-tracking/setup.md.txt).

This document discusses the following things that you can do when viewing a
fleet:

1. [Start tracking the fleet](https://developers.google.com/maps/documentation/mobility/operations/fleet-tracking/view-fleet.md.txt#track).
2. [Listen for events and handle errors](https://developers.google.com/maps/documentation/mobility/operations/fleet-tracking/view-fleet.md.txt#update).
3. [Stop tracking](https://developers.google.com/maps/documentation/mobility/operations/fleet-tracking/view-fleet.md.txt#stop).
4. [Track a single vehicle while viewing a fleet](https://developers.google.com/maps/documentation/mobility/operations/fleet-tracking/view-fleet.md.txt#track-one).

## Start tracking the fleet

To track a fleet, you need to instantiate a fleet location provider and
set location restrictions for the map viewport as described in the following
sections.

### Instantiate a fleet location provider

The JavaScript fleet tracking library includes a location provider that
fetches multiple vehicles from Fleet Engine.

To instantiate it, follow these steps:

1. **Use your project ID** as well as a reference to your token fetcher.

2. **Use a vehicle filter query** The vehicle filter query controls which
   vehicles the map displays. The filter is passed to Fleet Engine.

   - For on-demand services, use `vehicleFilter`, and review [`ListVehiclesRequest.filter`](https://developers.google.com/maps/documentation/mobility/fleet-engine/reference/trips/rpc/maps.fleetengine.v1.md.txt#listvehiclesrequest)
   - For scheduled tasks, use `deliveryVehicleFilter`, and review [`ListDeliveryVehiclesRequest.filter`](https://developers.google.com/maps/documentation/mobility/fleet-engine/reference/tasks/rpc/maps.fleetengine.delivery.v1.md.txt#maps.fleetengine.delivery.v1.ListDeliveryVehiclesRequest)
3. **Set the bounding are for vehicle display** . Use `locationRestriction` to
   limit the area in which to display vehicles on the map. The location
   provider isn't active until this is set. You can set location bounds either
   in the constructor, or after the constructor.

4. **Initialize the map view**.

The following examples show how to instantiate a fleet location provider for
both on-demand and scheduled task scenarios. These example also show how to use
the `locationRestriction` in the constructor to make the location provider
active.

#### On-demand trips

<br />

### JavaScript

<br />

```javascript
locationProvider =
    new google.maps.journeySharing
        .FleetEngineFleetLocationProvider({
          projectId,
          authTokenFetcher,

          // Optionally, specify location bounds to
          // limit which vehicles are
          // retrieved and immediately start tracking.
          locationRestriction: {
            north: 37.3,
            east: -121.8,
            south: 37.1,
            west: -122,
          },
          // Optionally, specify a filter to limit
          // which vehicles are retrieved.
          vehicleFilter:
            'attributes.foo = "bar" AND attributes.baz = "qux"',
        });
```

<br />

### TypeScript

<br />

```typescript
locationProvider =
    new google.maps.journeySharing
        .FleetEngineFleetLocationProvider({
          projectId,
          authTokenFetcher,

          // Optionally, specify location bounds to
          // limit which vehicles are
          // retrieved and immediately start tracking.
          locationRestriction: {
            north: 37.3,
            east: -121.8,
            south: 37.1,
            west: -122,
          },
          // Optionally, specify a filter to limit
          // which vehicles are retrieved.
          vehicleFilter:
            'attributes.foo = "bar" AND attributes.baz = "qux"',
        });
```

<br />

<br />

#### Scheduled tasks

<br />

### JavaScript

<br />

```javascript
locationProvider =
    new google.maps.journeySharing
        .FleetEngineDeliveryFleetLocationProvider({
          projectId,
          authTokenFetcher,

          // Optionally, specify location bounds to
          // limit which delivery vehicles are
          // retrieved and immediately make the location provider active.
          locationRestriction: {
            north: 37.3,
            east: -121.8,
            south: 37.1,
            west: -122,
          },
          // Optionally, specify a filter to limit
          // which delivery vehicles are retrieved.
          deliveryVehicleFilter:
            'attributes.foo = "bar" AND attributes.baz = "qux"',
        });
```

<br />

### TypeScript

<br />

```typescript
locationProvider =
    new google.maps.journeySharing
        .FleetEngineDeliveryFleetLocationProvider({
          projectId,
          authTokenFetcher,

          // Optionally, specify location bounds to
          // limit which delivery vehicles are
          // retrieved and immediately make the location provider active.
          locationRestriction: {
            north: 37.3,
            east: -121.8,
            south: 37.1,
            west: -122,
          },
          // Optionally, specify a filter to limit
          // which delivery vehicles are retrieved.
          deliveryVehicleFilter:
            'attributes.foo = "bar" AND attributes.baz = "qux"',
        });
```

<br />

<br />

To set `locationRestriction` after the constructor, add the
`locationProvider.locationRestriction` later in your code as
shown in the following JavaScript example.

> [!NOTE]
> **Note:** The example is for scheduled tasks, but to do this for on-demand trips, you would just use `google.maps.journeySharing.FleetEngineFleetLocationProvider` instead.

```javascript
   // You can choose to not set locationRestriction in the constructor.
   // In this case, the location provider *DOES NOT START* after this line, because
   // no locationRestriction is set.
   locationProvider = new google.maps.journeySharing.DeliveryFleetLocationProvider({
   ... // not setting locationRestriction here
   });

   // You can then set the locationRestriction *after* the constructor.
   // After this line, the location provider is active.
   locationProvider.locationRestriction = {
     north: 1,
     east: 2,
     south: 0,
     west: 1,
   };
```

### Set location restriction using the map viewport

You can also set `locationRestriction` bounds to match the area currently
visible in the map view.

#### On-demand trips

<br />

### JavaScript

<br />

```javascript
google.maps.event.addListenerOnce(
  mapView.map, 'bounds_changed', () => {
    const bounds = mapView.map.getBounds();
    if (bounds) {
      // If you did not specify a location restriction in the
      // location provider constructor, you may do so here.
      // Location tracking will start as soon as this is set.
      locationProvider.locationRestriction = bounds;
    }
  });
```

<br />

### TypeScript

<br />

```typescript
google.maps.event.addListenerOnce(
  mapView.map, 'bounds_changed', () => {
    const bounds = mapView.map.getBounds();
    if (bounds) {
      // If you did not specify a location restriction in the
      // location provider constructor, you may do so here.
      // Location tracking will start as soon as this is set.
      locationProvider.locationRestriction = bounds;
    }
  });
```

<br />

<br />

#### Scheduled tasks

<br />

### JavaScript

<br />

```javascript
google.maps.event.addListenerOnce(
  mapView.map, 'bounds_changed', () => {
    const bounds = mapView.map.getBounds();
    if (bounds) {
      // If you did not specify a location restriction in the
      // location provider constructor, you may do so here.
      // Location provider will start as soon as this is set.
      locationProvider.locationRestriction = bounds;
    }
  });
```

<br />

### TypeScript

<br />

```typescript
google.maps.event.addListenerOnce(
  mapView.map, 'bounds_changed', () => {
    const bounds = mapView.map.getBounds();
    if (bounds) {
      // If you did not specify a location restriction in the
      // location provider constructor, you may do so here.
      // Location provider will start as soon as this is set.
      locationProvider.locationRestriction = bounds;
    }
  });
```

<br />

<br />

### Initialize the map view

Once you construct the location provider, initialize the map view in the same
way you do when following a single vehicle.

After loading the JavaScript Journey Sharing library, initialize
the map view and add it to the HTML page. Your page should contain
a *\<div\>* element that holds the map view. The *\<div\>* element
is named *map_canvas* in the following examples.=

#### On-demand trips

<br />

### JavaScript

<br />

```javascript
const mapView = new
    google.maps.journeySharing.JourneySharingMapView({
  element: document.getElementById('map_canvas'),
  locationProviders: [locationProvider],
});

// If you did not specify a vehicle ID in the
// location provider constructor, you may do so here.
// Location tracking will start as soon as this is set.
locationProvider.vehicleId
                        = 'your-vehicle-id';

// Give the map an initial viewport to allow it to
// initialize; otherwise the 'ready' event above may
// not fire. The user also has access to the mapView
// object to customize as they want.
mapView.map.setCenter('Times Square, New York, NY');
mapView.map.setZoom(14);
```

<br />

### TypeScript

<br />

```typescript
const mapView = new
    google.maps.journeySharing.JourneySharingMapView({
  element: document.getElementById('map_canvas'),
  locationProviders: [locationProvider],
});

// If you did not specify a vehicle ID in the
// location provider constructor, you may do so here.
// Location tracking will start as soon as this is set.
locationProvider.VehicleId
                        = 'your-vehicle-id';

// Give the map an initial viewport to allow it to
// initialize; otherwise the 'ready' event above may
// not fire. The user also has access to the mapView
// object to customize as they want.
mapView.map.setCenter('Times Square, New York, NY');
mapView.map.setZoom(14);
```

<br />

<br />

#### Scheduled tasks

<br />

### JavaScript

<br />

```javascript
const mapView = new
    google.maps.journeySharing.JourneySharingMapView({
  element: document.getElementById('map_canvas'),
  locationProviders: [locationProvider],
});

// If you did not specify a delivery vehicle ID in the
// location provider constructor, you may do so here.
// Location tracking will start as soon as this is set.
locationProvider.deliveryVehicleId
                        = 'your-delivery-vehicle-id';

// Give the map an initial viewport to allow it to
// initialize; otherwise the 'ready' event above may
// not fire. The user also has access to the mapView
// object to customize as they want.
mapView.map.setCenter('Times Square, New York, NY');
mapView.map.setZoom(14);
```

<br />

### TypeScript

<br />

```typescript
const mapView = new
    google.maps.journeySharing.JourneySharingMapView({
  element: document.getElementById('map_canvas'),
  locationProviders: [locationProvider],
});

// If you did not specify a delivery vehicle ID in the
// location provider constructor, you may do so here.
// Location tracking will start as soon as this is set.
locationProvider.deliveryVehicleId
                        = 'your-delivery-vehicle-id';

// Give the map an initial viewport to allow it to
// initialize; otherwise the 'ready' event above may
// not fire. The user also has access to the mapView
// object to customize as they want.
mapView.map.setCenter('Times Square, New York, NY');
mapView.map.setZoom(14);
```

<br />

<br />

## Listen for events and handle errors

Once you've started following the fleet, you need to listen for event changes
and handle any errors that arise as described in the following sections.

### Listen for change events

You can retrieve meta information about the fleet from the vehicle object using
the location provider. Changes to the meta information trigger an *update*
event. The meta information includes vehicle properties such as navigation
state, remaining distance, and custom attributes.

For details, refer to the following:

- [On-demand trips vehicle options reference](https://developers.google.com/maps/documentation/javascript/reference/journey-sharing-fleet-tracking-odrd.md.txt#FleetEngineVehicleLocationProviderOptions)
- [Scheduled tasks vehicle options reference](https://developers.google.com/maps/documentation/javascript/reference/journey-sharing-fleet-tracking-odrd.md.txt#FleetEngineVehicleLocationProviderOptions)

The following examples show how to listen to these change events.

#### On-demand trips

<br />

### JavaScript

<br />

```javascript
locationProvider.addListener('update', e => {
  // e.vehicles contains data that may be
  // useful to the rest of the UI.
  for (vehicle of e.vehicles) {
    console.log(vehicle.navigationStatus);
  }
});
```

<br />

### TypeScript

<br />

```typescript
locationProvider.addListener('update',
    (e: google.maps.journeySharing.FleetEngineFleetLocationProviderUpdateEvent) => {
  // e.vehicles contains data that may be
  // useful to the rest of the UI.
  if (e.vehicles) {
    for (vehicle of e.vehicles) {
      console.log(vehicle.navigationStatus);
    }
  }
});
```

<br />

<br />

#### Scheduled tasks

<br />

### JavaScript

<br />

```javascript
locationProvider.addListener('update', e => {
  // e.deliveryVehicles contains data that may be
  // useful to the rest of the UI.
  if (e.deliveryVehicles) {
    for (vehicle of e.deliveryVehicles) {
      console.log(vehicle.remainingDistanceMeters);
    }
  }
});
```

<br />

### TypeScript

<br />

```typescript
locationProvider.addListener('update',
    (e: google.maps.journeySharing.FleetEngineDeliveryFleetLocationProviderUpdateEvent) => {
  // e.deliveryVehicles contains data that may be
  // useful to the rest of the UI.
  if (e.deliveryVehicles) {
    for (vehicle of e.deliveryVehicles) {
      console.log(vehicle.remainingDistanceMeters);
    }
  }
});
```

<br />

<br />

### Listen for errors

You also want to listen for and handle errors that happen while following a
vehicle. Errors that arise asynchronously from requesting vehicle
information trigger error events.

The following example shows how to listen for
these events so you can handle errors.

<br />

### JavaScript

<br />

```javascript
locationProvider.addListener('error', e => {
  // e.error is the error that triggered the event.
  console.error(e.error);
});
```

<br />

### TypeScript

<br />

```typescript
locationProvider.addListener('error', (e: google.maps.ErrorEvent) => {
  // e.error is the error that triggered the event.
  console.error(e.error);
});
```

<br />

<br />

## Stop tracking the fleet

To stop tracking the fleet, you set the bounds of the location provider to null,
and then remove the location provider from the map view as described in the
following sections.

### Set the location provider bounds to null

To stop the location provider from tracking the fleet, set the bounds
of the location provider to null.

#### On-demand trips

<br />

### JavaScript

<br />

```javascript
locationProvider.locationRestriction = null;
```

<br />

### TypeScript

<br />

```typescript
locationProvider.locationRestriction = null;
```

<br />

<br />

#### Scheduled tasks

<br />

### JavaScript

<br />

```javascript
locationProvider.locationRestriction = null;
```

<br />

### TypeScript

<br />

```typescript
locationProvider.locationRestriction = null;
```

<br />

<br />

### Remove the location provider from the map view

The following example shows how to remove a location provider from the map view.

<br />

### JavaScript

<br />

```javascript
mapView.removeLocationProvider(locationProvider);
```

<br />

### TypeScript

<br />

```typescript
mapView.removeLocationProvider(locationProvider);
```

<br />

<br />

## Track a delivery vehicle while viewing a delivery fleet

If you are using Mobility services for scheduled tasks, you can both view a
fleet and display the route and upcoming tasks for a specific delivery vehicle
in that same map view. To do this, instantiate both a Delivery Fleet Location
Provider and a Delivery Vehicle Location Provider, and add them both to the map
view. Once instantiated, the delivery fleet location provider starts to show
delivery vehicles on the map. The following examples show how to instantiate
both location providers:

<br />

### JavaScript

<br />

```javascript
deliveryFleetLocationProvider =
    new google.maps.journeySharing
        .FleetEngineDeliveryFleetLocationProvider({
          projectId,
          authTokenFetcher,

          // Optionally, specify location bounds to
          // limit which delivery vehicles are
          // retrieved and immediately start tracking.
          locationRestriction: {
            north: 37.3,
            east: -121.8,
            south: 37.1,
            west: -122,
          },
          // Optionally, specify a filter to limit
          // which delivery vehicles are retrieved.
          deliveryVehicleFilter:
            'attributes.foo = "bar" AND attributes.baz = "qux"',
        });

deliveryVehicleLocationProvider =
    new google.maps.journeySharing
        .FleetEngineDeliveryVehicleLocationProvider({
          projectId,
          authTokenFetcher
        });

const mapView = new
    google.maps.journeySharing.JourneySharingMapView({
  element: document.getElementById('map_canvas'),
  locationProviders: [
    deliveryFleetLocationProvider,
    deliveryVehicleLocationProvider,
  ],
  // Any other options
});
```

<br />

### TypeScript

<br />

```typescript
deliveryFleetLocationProvider =
    new google.maps.journeySharing
        .FleetEngineDeliveryFleetLocationProvider({
          projectId,
          authTokenFetcher,

          // Optionally, specify location bounds to
          // limit which delivery vehicles are
          // retrieved and immediately start tracking.
          locationRestriction: {
            north: 37.3,
            east: -121.8,
            south: 37.1,
            west: -122,
          },
          // Optionally, specify a filter to limit
          // which delivery vehicles are retrieved.
          deliveryVehicleFilter:
            'attributes.foo = "bar" AND attributes.baz = "qux"',
        });

deliveryVehicleLocationProvider =
    new google.maps.journeySharing
        .FleetEngineDeliveryVehicleLocationProvider({
          projectId,
          authTokenFetcher
        });

const mapView = new
    google.maps.journeySharing.JourneySharingMapView({
  element: document.getElementById('map_canvas'),
  locationProviders: [
    deliveryFleetLocationProvider,
    deliveryVehicleLocationProvider,
  ],
  // Any other options
});
```

<br />

<br />

### Use marker customization to track a delivery vehicle

To enable the delivery vehicle location provider to track a delivery vehicle
when you click its fleet marker, follow these steps:

1. Customize a marker and add a click action.

2. Hide the marker to prevent duplicate markers.

   > [!NOTE]
   > **Note:** The delivery fleet location provider renders a set of markers, one for each vehicle tracked. If you want to show details for one vehicle when the user clicks that vehicle, you instantiate a delivery vehicle location provider, and set the vehicle ID to be the one the user clicked, as shown in the following example. When you do this, however, the delivery vehicle location provider also renders a marker for this vehicle (as it is designed to do). So you hide one of them so there are not two markers for the same vehicle.

Examples for these steps are in the following sections.

#### Customize a marker and add a click action

<br />

### JavaScript

<br />

```javascript
// Specify the customization function either separately, or as a field in
// the options for the delivery fleet location provider constructor.
deliveryFleetLocationProvider.deliveryVehicleMarkerCustomization =
  (params) => {
    if (params.isNew) {
      params.marker.addListener('click', () => {
        // params.vehicle.name follows the format
        // "providers/{provider}/deliveryVehicles/{vehicleId}".
        // Only the vehicleId portion is used for the delivery vehicle
        // location provider.
        deliveryVehicleLocationProvider.deliveryVehicleId =
            params.vehicle.name.split('/').pop();
      });
    }
  };
```

<br />

### TypeScript

<br />

```typescript
// Specify the customization function either separately, or as a field in
// the options for the delivery fleet location provider constructor.
deliveryFleetLocationProvider.deliveryVehicleMarkerCustomization =
  (params: google.maps.journeySharing.DeliveryVehicleMarkerCustomizationFunctionParams) => {
    if (params.isNew) {
      params.marker.addListener('click', () => {
        // params.vehicle.name follows the format
        // "providers/{provider}/deliveryVehicles/{vehicleId}".
        // Only the vehicleId portion is used for the delivery vehicle
        // location provider.
        deliveryVehicleLocationProvider.deliveryVehicleId =
            params.vehicle.name.split('/').pop();
      });
    }
  };
```

<br />

<br />

#### Hide the marker to prevent duplicate markers

Hide the marker from the delivery vehicle location provider to prevent rendering
two markers for the same vehicle:

<br />

### JavaScript

<br />

```javascript
// Specify the customization function either separately, or as a field in
// the options for the delivery vehicle location provider constructor.
deliveryVehicleLocationProvider.deliveryVehicleMarkerCustomization =
  (params) => {
    if (params.isNew) {
      params.marker.setVisible(false);
    }
  };
```

<br />

### TypeScript

<br />

```typescript
// Specify the customization function either separately, or as a field in
// the options for the delivery vehicle location provider constructor.
deliveryVehicleLocationProvider.deliveryVehicleMarkerCustomization =
  (params: deliveryVehicleMarkerCustomizationFunctionParams) => {
    if (params.isNew) {
      params.marker.setVisible(false);
    }
  };
```

<br />

<br />

## What's next

- [Style a map](https://developers.google.com/maps/documentation/mobility/operations/fleet-tracking/style.md.txt)