# JavaScript methods

> Reference for window.GeoEngage: read the visitor's location, track events and conversions, identify visitors and set attributes.

Every method lives on `window.GeoEngage`, and every one on this page can be called as soon as the tag has run, except `getLocation` and `getAttributes`: ask those inside `onReady`. See [Calling the API](https://geoengage.app/docs/widget#calling-the-api).

## Location

### `getLocation`

```ts
GeoEngage.getLocation(): Location | null
```

The visitor's location, looked up from their IP address and cached in their browser for an hour. `null` until the first lookup has finished, so ask for it inside [`onReady`](https://geoengage.app/docs/widget/events#onready), where it never is.

```js
GeoEngage.onReady((ge) => {
  if (ge.getLocation().country_code === 'DE') {
    document.querySelector('#delivery-note').textContent = 'Free delivery across Germany';
  }
});
```

A visitor in São Paulo:

```json
{
  "continent": "South America",
  "continent_code": "SA",
  "country": "Brazil",
  "country_code": "BR",
  "region": "SP",
  "region_name": "São Paulo",
  "city": "São Paulo",
  "zip": "01000-000",
  "lat": -23.5475,
  "lon": -46.6361,
  "timezone": "America/Sao_Paulo",
  "ip": "198.51.100.23",
  "source": "cloudfront"
}
```

- Compare `country_code`, the two-letter ISO code. `country` is the country's name when that's known, and the code otherwise.
- A field the lookup couldn't determine is left out, rather than sent empty.
- A visitor who can't be placed at all gets `{ "source": "unknown", "timezone": "…" }`, with the timezone from their browser.

## Tracking

### `trackEvent`

```ts
GeoEngage.trackEvent(name: string, properties?: object): void
```

Records a custom event, for things the widget can't see by itself: a video played, a wizard step completed, a filter applied.

```js
GeoEngage.trackEvent('video_played', { videoid: 'intro', seconds: 42 });
```

Events are grouped by name, so keep names short and stable: `signup_started`, not `Signup started on the pricing page`. Put the detail in `properties` instead. Any key is fine, including `name` or `page`. Use lowercase names: they are stored lowercase, so `videoId` reads back as `videoid`. A call without a name, or with one longer than 100 characters, is ignored.

**Custom Events** in the dashboard lists each name with its events per day, the share of visits that sent it, and when it last arrived. Open one to see how often each property value came up, and which countries and devices send it. Custom events never count as conversions: use [`trackConversion`](#trackconversion) with a goal for that.

### `trackConversion`

```ts
GeoEngage.trackConversion(name: string, value?: number, metadata?: object): void
```

Reports a conversion that only your code knows about: an order that went through, a signup your server accepted. Call it where the conversion actually happens, such as your order confirmation page.

```js
GeoEngage.trackConversion('purchase', 99.0, {
  orderid: 'ORD-12345',
  currency: 'USD',
});
```

Reports count a conversion only when a goal claims it: create a *Conversion from code* or *Revenue* goal in **Goals** with the same name. The goal counts every call on record with that name, including calls made before you created it. A Revenue goal also adds up `value`. The other goal types — page visit, element click and form submit — need no code at all. See [Goals and conversions](https://geoengage.app/docs/analytics/goals).

A name is recorded once per page view: if your confirmation page calls `trackConversion('purchase', ...)` twice, the first call is kept and the second is ignored. In a single-page app each route change is a new page view.

`metadata` is kept with the conversion and shown on the goal's own page under **Goals**, grouped by value. Use lowercase names: they are stored lowercase, so `orderId` reads back as `orderid`. Describe the conversion rather than the person — a plan or a currency, not an email address.

## Visitors

### `identify`

```ts
GeoEngage.identify(email: string): void
```

Ties the current visitor to an email address. Call it when someone signs in or signs up. Every event recorded afterwards carries the email, until `clearIdentity()` removes it.

```js
GeoEngage.identify('jane@example.com');
```

> [!IMPORTANT]
> An email address is personal data. Only call `identify` where your privacy policy covers it, and after consent wherever consent is required.

### `clearIdentity`

```ts
GeoEngage.clearIdentity(): void
```

Forgets the email set by `identify`. Call it when someone signs out.

### `setAttributes`

```ts
GeoEngage.setAttributes(attributes: object): object
```

Stores what your own systems know about the visitor — their plan, their company size, whether they're already a customer — so rules can target it with the **Visitor Attribute** condition. Returns all of the visitor's attributes.

```js
GeoEngage.setAttributes({ plan: 'pro', seats: 12 });
```

- Calls merge. A later `setAttributes({ seats: 20 })` changes `seats` and keeps `plan`.
- Attributes are kept in the visitor's browser, so a value set inside your app is still there when they visit your pricing page.
- Setting an attribute doesn't re-run the rules on the current page. It takes effect from the next page view or route change, so set attributes as early as you can.

### `getAttributes`

```ts
GeoEngage.getAttributes(): object
```

The attributes stored for this visitor.

### `clearAttributes`

```ts
GeoEngage.clearAttributes(): void
```

Removes every stored attribute, for example when someone signs out.

## Configuration

### `configure`

```ts
GeoEngage.configure(options: { excludeSelectors?, customSelectors?, tracking? }): void
```

Changes the tracking settings for the current page, on top of those from **Tracking Config** in the dashboard. Each option you pass replaces the current value, so pass the complete list.

```js
GeoEngage.configure({
  excludeSelectors: ['.account-menu', '[data-private]'],
  customSelectors: [{ selector: '.checkout-button', name: 'Checkout' }],
});
```

| Option | What it does |
| --- | --- |
| `excludeSelectors` | Elements the click tracker ignores. |
| `customSelectors` | Extra elements to track as calls to action, as `{ selector, name }`. |
| `tracking` | Other overrides, such as `autoTrack: { clicks, forms, scroll, links }`. |

### `notifyRouteChange`

```ts
GeoEngage.notifyRouteChange(): void
```

Tells the widget the page changed without a full reload: it removes the current actions, checks your rules again and records a page view. Only needed for a router that doesn't use the History API; see [Single-page apps](https://geoengage.app/docs/widget/single-page-apps#telling-the-widget-yourself). A call made before the widget is ready does nothing, because its first page view is of the page the visitor is on by then.

## Consent and events

- `grantConsent()`, `revokeConsent()` and `hasConsent()` are covered in [Consent mode](https://geoengage.app/docs/widget/consent#the-consent-api).
- `onReady()`, `onAction()`, `onEvent()` and `onExitIntent()` are covered in [Widget events](https://geoengage.app/docs/widget/events).

---

Source: https://geoengage.app/docs/widget/methods
