# Shopper Geolocation

Geolocation plays a crucial role in providing personalized experiences based on shopper location. Use this guide to integrate [Shopper Context API](https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-context?meta=Summary) geolocation features with your storefront for enhanced shopper experiences.

With B2C Commerce version 24.7, work with geolocation information in the following ways:

- Look up a shopper's location using the client's IP address.
- Look up a shopper's location using the client's IP address and use that information to set context for subsequent requests.
- Manually provide a location and use that information in subsequent requests.

:::note
- When you use SCAPI to retrieve geolocation information, the client's IP address is used to retrieve geolocation information from the B2C Commerce platform, and the IP lookup is based on your database information. For details, see [Geolocation Lookup for IP Addresses](https://help.salesforce.com/s/articleView?id=cc.b2c_geolocation_lookup_for_ip_addresses.htm\&type=5).
- An association with a location impacts future requests. For example, you have a dynamic customer group for which membership includes `request.geolocation.city == 'San Francisco'`. For the purposes of group membership evaluation, this geolocation location applies to subsequent requests for this shopper. For details, see [Customer Segmentation Via Geolocation](https://help.salesforce.com/s/articleView?id=cc.b2c_customer_segmentation_via_geolocation.htm\&language=en_US\&type=5).
:::

## Enable Shopper Context

1. Log in to Business Manager.
2. Click App Launcher ![App Launcher](https://a.sfdcstatic.com/developer-website/sfdocs/commerce-cloud/media/shared/appLauncher.png) and then select **Administration** > **Global Preferences** > **Feature Switches**.
3. Check **Enable Shopper Context**.

## Retrieve Geolocation with Client IP Address

:::important
The SCAPI geolocation service does not support Anycast-related IP addresses. Anycast allows the same IP in multiple locations, and, therefore, can't resolve to one single location.
:::

Using SCAPI, geolocation information is retrieved using the client's IP address to look up geolocation information in the B2C Commerce platform.

Include the `clientIp` attribute with a Shopper Context [PATCH](https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-context?meta=updateShopperContext) or [PUT](https://developer.salesforce.com/docs/commerce/commerce-api/references/shopper-context?meta=createShopperContext) request, for example:

```sh
curl 'https://$CODE.api.commercecloud.salesforce.com/shopper/shopper-context/v1/organizations/$ORG/shopper-context/$USID' \
	    --method 'PUT' \
	    --header 'Authorization: Bearer $TOKEN' \
	    --header 'Content-Type: application/json' \
	    --data '{ "clientIp": "13.108.0.0" }'
```

The following keys are provided in the HTTP response header `x-geolocation`, and are delimited with semicolons (;):

- CountryCode
- Country
- City
- PostalCode
- MetroCode
- Region
- RegionCode
- Latitude
- Longitude

```text
x-geolocation: CountryCode: US; Country: United States; City: San Francisco; PostalCode: 94105; MetroCode: 820; Region: San Francisco; RegionCode: CA; Latitude: 37.7749; Longitude: -122.4194
```

:::note
Consume the geolocation HTTP response header in a case insensitive way, because it can be returned as `x-geolocation` or `X-Geolocation`.
:::

## Retrieve and Use Geolocation from Client IP

Retrieving geolocation with `clientIp` returns information, but does not impact subsequent requests. To use the location provided by `clientIp` on subsequent requests, you must specify the `evaluateContextWithClientIp` query parameter:

If `evaluateContextWithClientIp` is set to `true:`

- the `clientIP` is saved and is used with subsequent requests.

If `evaluateContextWithClientIp` is set to `false`:

- the clientIP is not saved and is not used with subsequent requests.

In both cases, the `x-geolocation` response header is returned. Null or empty values are not returned.

## Retrieve Geolocation with `geoLocation` Attribute and Set Context

You can also use the `geoLocation` attribute to set a specific context geolocation. You can collect a user’s location via native browser functionality (navigator.geolocation) or via manual user input, and send these coordinates to the Shopper Context API for site personalization.

You can manually set any combination of the following optional parameters:

- countryCode
- country
- city
- postalCode
- metroCode
- region
- regionCode
- latitude
- longitude

The following Shopper Context example request provides the `city` and `countryCode` parameters in the `geoLocation` attribute to set the geolocation information:

```json
{
   "clientIp": "12.12.12.1",
    "geoLocation": {
      "city": "Boston",
      "countryCode": "US"
    }
}
```

THe `x-geolocation` response header returned is:

```text
x-geolocation: CountryCode: US; City: Boston;
```

:::important
If you set a location using the `geoLocation` attribute in the request body, it is saved as context for subsequent requests. If both `geoLocation` and `clientIp` are set in the context, the location set with `geoLocation` takes precedence over the location resolved from the `clientIp`.
:::

For example, let's assume the following promotion configuration:

- For New York, USA: 20% discount on women's tops.
- For Boston, USA: 15% discount on women's tops.

In the following Shopper Context request, both `clientIp` and `geoLocation` attributes are provided. In this case, the `geoLocation` value takes precedence and the response header `x-geolocation` returns the location based on the `geoLocation` attribute in the request:

```sh
curl 'https://$CODE.api.commercecloud.salesforce.com/shopper/shopper-context/v1/organizations/$ORG/shopper-context/$USID' \
	    --method 'PUT' \
	    --header 'Authorization: Bearer $TOKEN' \
	    --header 'Content-Type: application/json' \
	    --data '{ "clientIp": "12.12.12.1",
                "geoLocation": {
                    "countryCode": "US",
                    "country": "United States of America",
                    "city": "Boston",
                    "postalCode": "01730",
                    "metroCode": "M234",
                    "region": "NA",
                    "regionCode": "12345",
                    "latitude": 10.11,
                    "longitude": 198.34
                }
              }'
```

The following `x-geolocation` response header is returned:

```text
x-geolocation: CountryCode: US; Country: United States of America; City: Boston; PostalCode: 01730; MetroCode: M234; Region: NA; RegionCode: 12345; Latitude: 10.11; Longitude: 198.34
```

Suppose the `clientIp` 12.12.12.1 resolves to New York, USA, but because the `geoLocation` in the payload specifies Boston, US, the context is evaluated based on Boston-specific promotions, resulting in a 15% discount on women's tops.

### Prompt the User for Geolocation

In this case, you provide a prompt for the user to enter geolocation information, which you can then send to the Shopper Context API, for example:

#### Provide Latitude and Longitude

```sh
curl 'https://$CODE.api.commercecloud.salesforce.com/shopper/shopper-context/v1/organizations/$ORG/shopper-context/$USID' \
    --method 'PUT' \
    --header 'Authorization: Bearer $TOKEN' \
    --header 'Content-Type: application/json' \
    --data '{ "geoLocation": { "latitude": 37.7749, "longitude": -122.4194 } }'
```

#### Provide Other Location Data

```sh
curl 'https://$CODE.api.commercecloud.salesforce.com/shopper/shopper-context/v1/organizations/$ORG/shopper-context/$USID' \
    --method 'PUT' \
    --header 'Authorization: Bearer $TOKEN' \
    --header 'Content-Type: application/json' \
    --data '{ "geoLocation": { "countryCode": "US", "city": "San Francisco" } }'
```

## Update Geolocation For Use in Subsequent Requests

When the `geoLocation` attribute is updated in Shopper Context PATCH calls, the entire existing geolocation value is replaced, not individual property values. To make a change to the geolocation, you must send all required properties, because geolocation properties work together.

You can set a new location context using the `geoLocation` attribute in the request body. The `geoLocation` attribute contains:

- `countryCode`
- `country`
- `city`
- `postalCode`
- `metroCode`
- `region`
- `regionCode`
- `latitude`
- `longitude`

Null values are not returned.

## Geolocation with Hooks

From a Script API perspective, [dw.system.Request.getGeoLocation](https://salesforcecommercecloud.github.io/b2c-dev-doc/docs/upcoming/scriptapi/html/api/class_dw_system_Request.html#dw_system_Request_getGeolocation_DetailAnchor)\` returns the following geolocation information, which is useful when using hooks:

- City: `request.geolocation.city`
- Country Name: `request.geolocation.countryName`
- Country Code: `request.geolocation.countryCode`
- Latitude: `request.geolocation.latitude`
- Longitude: `request.geolocation.longitude`
- Metro Code: `request.geolocation.metroCode`
- Postal Code: `request.geolocation.postalCode`
- Region Name: `request.geolocation.regionName`
- Region Code: `request.geolocation.regionCode`
