
The Go SDK lets you send events to Amplitude from your Go application.

## Install the SDK

Install the dependencies.

```bash
go get github.com/amplitude/analytics-go
```

## Initialize the SDK

You must initialize the SDK before you can instrument any events. The API key for your Amplitude project constructs a Config `struct`. Use that Config `struct` to initialize a client `struct` that implements the Client interface. You can use the client across requests after you initialize it. Refer to the examples in the next section.

```go
import (
    "github.com/amplitude/analytics-go/amplitude"
)

config := amplitude.NewConfig(AMPLITUDE_API_KEY)

client := amplitude.NewClient(config)
```

## Configure the SDK

| Name                     | Description                                                                                                                                                                                                     | Default Value                                                        |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- |
| `APIKey`                 | Required. `string`. The API key of the Amplitude project. The Client `struct` sends events to this project. Set this when you initialize the Client `struct`.                                                   | `nil`                                                                |
| `FlushQueueSize`         | `int`. Events wait in the buffer and send in a batch. The SDK flushes the buffer when the number of events reaches `FlushQueueSize`.                                                                             | `200`                                                                |
| `FlushInterval`          | `time.Duration`. Events wait in the buffer and send in a batch. The SDK flushes the buffer every `FlushInterval`.                                                                                                | `10 seconds`                                                         |
| `FlushMaxRetries`        | `int`. The number of times the client retries an event when the request returns an error.                                                                                                                       | `12`                                                                 |
| `RetryBaseInterval`      | `time.Duration`. Base interval between retries when the request returns an error.                                                                                                                               | `100 milliseconds`                                                   |
| `RetryThrottledInterval` | `time.Duration`. Base interval between retries for throttled requests.                                                                                                                                          | `30 seconds`                                                         |
| `Logger`                 | Logger interface. The logger the Amplitude client uses.                                                                                                                                                          | [`Go standard Logger`](https://pkg.go.dev/log#Logger): `log.Logger`. |
| `ServerZone`             | `string`. The server zone of the projects. Supports EU and US. For EU data residency, change to EU.                                                                                                             | `US`                                                                 |
| `ServerURL`              | `string`. The API endpoint URL that the SDK sends events to. `ServerZone` and `UseBatch` select this URL automatically. If you set this field, the SDK ignores `ServerZone` and `UseBatch` and uses the string value. | `https://api2.amplitude.com/2/httpapi`                               |
| `UseBatch`               | `boolean`. Whether to use [batch api](/docs/apis/analytics/batch-event-upload). By default, the SDK uses the default `serverUrl`.                                                                           | `false`                                                              |
| `StorageFactory`         | `function`. Creates the storage struct that holds events in the storage buffer. Events in the storage buffer wait to send.                                                                                | `InMemoryStorage`                                                    |
| `OptOut`                 | `bool`. Opt out option. If set to `true`, the client doesn't process or send events.                                                                                                                               | `false`                                                              |
| `ConnectionTimeout`      | `time.Duration`. A time limit for API requests.                                                                                                                                                                 | `10 seconds`                                                         |
| `MaxStorageCapacity`     | `int`. The maximum count of pending events in the storage.                                                                                                                                                      | `20000`                                                              |
| `MinIDLength`            | `int`. The minimum length of user_id and device_id.                                                                                                                                                             | `5`                                                                  |
| `ExecuteCallback`        | `function`. Client level callback function.                                                                                                                                                                     | `nil`                                                                |

Set your configuration before you initialize a client.

### Configure batching behavior

To support high-performance environments, the SDK sends events in batches. The SDK queues every event logged by the `track` method in memory and flushes events in batches in the background. You can customize batch behavior with `FlushQueueSize` and `FlushInterval`. By default, the SDK runs in regular mode with `serverUrl` set to `https://api2.amplitude.com/2/httpapi`. To send large batches of data at a time, switch to batch mode by setting `UseBatch` to `true`, which sets `setServerUrl` to the batch event upload API `https://api2.amplitude.com/batch`. Both regular mode and batch mode use the same flush queue size and flush intervals.

```go
package main

import (
    "github.com/amplitude/analytics-go/amplitude"
)

func main() {
    // Create a Config struct
    config := amplitude.NewConfig(AMPLITUDE_API_KEY)

    // Events queued in memory will flush when number of events exceed upload threshold
    // Default value is 200
    config.FlushQueueSize = 100
    // Events queue will flush every certain milliseconds based on setting
    // Default value is 10 seconds
    config.FlushInterval = 5000
    // Pass a Config struct
    // to initialize a Client struct
    // which implements Client interface
    client := amplitude.NewClient(config)
}
```

## Track an event

Events represent how users interact with your application. For example, "Button Clicked" represents an action you want to note.

```go
// Track a basic event
// EventOne of UserID and DeviceID is required as well as EventType
client.Track(amplitude.Event{
    UserID:    "user-id",
    EventType: "Button Clicked",
})

// Track events with optional properties
client.Track(amplitude.Event{
    UserID:    "user-id",
    EventType: "Button Clicked",
    EventProperties: map[string]interface{}{
        "name":       "Checkout",
        "a property": "a value",
    },
    EventOptions: amplitude.EventOptions{
        Price: 1.99,
    },
})
```

## User properties

User properties help you understand your users when they perform actions within your app, such as their device details, preferences, or languages.

Use `Identify` to set the user properties of a particular user without sending any event. The SDK supports the operations `Set`, `SetOnce`, `Unset`, `Add`, `Append`, `Prepend`, `PreInsert`, `PostInsert`, `Remove`, and `ClearAll` on individual user properties. The SDK declares the operations as `Identify` struct methods. You can chain multiple operations together in a single `Identify` struct, then pass the struct to the Amplitude client to send to the server.

{% callout type="note" heading="" %}
If you send the Identify call after the event, the operation results appear immediately in the dashboard user's profile area, but they don't appear in chart results until you send another event after the Identify call. The Identify call only affects events going forward. For more details, refer to [User properties and events](/docs/data/user-properties-and-events).
{% /callout %}

The `Identify` struct provides controls over setting user properties. First instantiate an `Identify` struct, then call `Client.Identify()` methods on it.

```Go
identifyObj := amplitude.Identify{}
client.Identify(identifyObj, amplitude.EventOptions{UserID: "user-id"})
```

### Identify.Set

This method sets the value of a user property. For example, you can set a role property for a user.

```Go
identifyObj := amplitude.Identify{}
identifyObj.Set("location", "LAX")
client.Identify(identifyObj, amplitude.EventOptions{UserID: "user-id"})
```

### Identify.SetOnce

This method sets the value of a user property only once. `SetOnce()` ignores subsequent calls. For example, you can set an initial login method for a user. The SDK tracks only the initial value.

```Go
identifyObj := amplitude.Identify{}
identifyObj.SetOnce("initial-location", "SFO")
client.Identify(identifyObj, amplitude.EventOptions{UserID: "user-id"})
```

### Identify.Add

This method increments a user property by a numerical value. If the user property doesn't have a value set yet, the SDK initializes the property to 0 before incrementing it. For example, you can track a user's travel count.

```Go
identifyObj := amplitude.Identify{}
identifyObj.Add("travel-count", 1)
client.Identify(identifyObj, amplitude.EventOptions{UserID: "user-id"})
```

### Arrays in user properties

You can use arrays as user properties. You can directly set arrays or use `Prepend()`, `Append()`, `PreInsert()`, and `PostInsert()` to generate an array.

#### Identify.Prepend

This method prepends a value or values to a user property array. If the user property doesn't have a value set yet, the SDK initializes the property to an empty list before prepending the new values.

```Go
identifyObj := amplitude.Identify{}
identifyObj.Prepend("visited-locations", "LAX")
client.Identify(identifyObj, amplitude.EventOptions{UserID: "user-id"})
```

#### Identify.Append

This method appends a value or values to a user property array. If the user property doesn't have a value set yet, the SDK initializes the property to an empty list before appending the new values.

```Go
identifyObj := amplitude.Identify{}
identifyObj.Append("visited-locations", "SFO")
client.Identify(identifyObj, amplitude.EventOptions{UserID: "user-id"})
```

#### Identify.PreInsert

This method pre-inserts a value or values to a user property if the value doesn't exist in the user property yet. Pre-insert means inserting the value at the beginning of a given list. If the user property doesn't have a value set yet, the SDK initializes the property to an empty list before pre-inserting the new values. If the user property has an existing value, the SDK performs no operation.

```Go
identifyObj := amplitude.Identify{}
identifyObj.PreInsert("unique-locations", "LAX")
client.Identify(identifyObj, amplitude.EventOptions{UserID: "user-id"})
```

#### Identify.PostInsert

This method post-inserts a value or values to a user property if the value doesn't exist in the user property yet. Post-insert means inserting the value at the end of a given list. If the user property doesn't have a value set yet, the SDK initializes the property to an empty list before post-inserting the new values. If the user property has an existing value, the SDK performs no operation.

```Go
identifyObj := amplitude.Identify{}
identifyObj.PostInsert("unique-locations", "SFO")
client.Identify(identifyObj, amplitude.EventOptions{UserID: "user-id"})
```

#### Identify.Remove

This method removes a value or values from a user property if the value exists in the user property. Remove means remove the existing value from the given list. If the item doesn't exist in the user property, the SDK performs no operation.

```Go
identifyObj := amplitude.Identify{}
identifyObj.Remove("unique-locations", "JFK")
client.Identify(identifyObj, amplitude.EventOptions{UserID: "user-id"})
```

## User groups

Amplitude supports assigning users to groups and performing queries such as Count by Distinct on those groups. For example, you can group your users by the organization they're in by using an `orgId`. You can designate Joe to be in `orgId` `10` and Sue in `orgId` `15`. When you run a query in Amplitude's Event Segmentation chart, select "..performed by" `orgId` to query the number of organizations that performed a specific event. As long as at least one member of that group performed the event, Amplitude includes that group in the count.

When you set groups, define a `groupType` and `groupName`. In the previous example, `orgId` is the `groupType`, and each value, `10` and `15`, is a `groupName`. Another `groupType` example is `sport`, with `groupName` values like `tennis` and `baseball`. Use `SetGroup()` to designate which groups a user belongs to. `SetGroup()` also sets the `groupType:groupName` as a user property. `SetGroup()` overwrites any existing `groupName` value set for that user's `groupType`, and the corresponding user property value. `groupType` is a string, and `groupName` is an array of strings to show that a user belongs to one group or multiple groups. For example, if Joe is in `orgId` `10` and `16`, the `groupName` is `[10, 16]`. Your code might look like this:

```Go
// set group with single group name
client.SetGroup("org-id", []string{"15"}, amplitude.EventOptions{UserID: "user-id"})

// set group with multiple group names
client.SetGroup("org-id", []string{"15", "21"}, amplitude.EventOptions{UserID: "user-id"})
```

Set event-level groups using the `Groups` attribute of events:

```Go
// set groups when initial an Event struct
event := amplitude.Event{
    UserID:          "user-id",
    EventType:       "event-type",
    Groups: map[string][]string{"org-id": {"15", "21"}},
  }

// set groups for an existing Event struct
event.Groups["Sport"] = []string{"soccer"}

client.Track(event)
```

## Group properties

Use the Group Identify API to set or update the properties of particular groups. These updates only affect events going forward.

The `GroupIdentify()` method accepts a group type, a group name string parameter, and an Identify struct to apply to the group.

```Go
identifyObj := amplitude.Identify{}
identifyObj.Set("local", "en-us")
client.GroupIdentify("org-id", "15", identifyObj, amplitude.EventOptions{})
```

## Track revenue

The preferred method of tracking revenue for a user is to use `Revenue()` with the Revenue interface. The Revenue `struct` stores each revenue transaction and lets you define several special revenue properties, such as `RevenueType` and `ProductID`, that Amplitude's Event Segmentation and Revenue LTV charts use. Pass these Revenue structs into `Revenue` to send as revenue events to Amplitude. Amplitude then automatically displays revenue-relevant data in the platform. You can track both in-app and non-in-app purchases.

To track revenue from a user, call `Revenue()` each time a user generates revenue. For example, a user purchased 3 units of a product at $3.99.

```Go
revenueObj := amplitude.Revenue{
    Price:       3.99,
    Quantity:    3,
    ProductID:   "com.company.productID",
}
client.Revenue(revenueObj, amplitude.EventOptions{UserID: "user-id"})
```

### Revenue interface

| Name                                                                        | Type                   | Description                                                                                                        | Default |
| --------------------------------------------------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------ | ------- |
| ProductID (optional)                                                        | string                 | An identifier for the product. Amplitude recommends something like the Google Play Store product ID.               | ""      |
| Quantity (optional)                                                         | int                    | The quantity of products purchased. `Revenue = Quantity * Price`                                                   | 0       |
| Price (optional \*required for revenue data if the revenue field isn't set) | float64                | The price of the products purchased. You can use negative values to indicate refunds. `Revenue = Quantity * Price` | 0       |
| RevenueType (optional)                                                      | string                 | The revenue type (for example, tax, refund, income).                                                               | ""      |
| Receipt (optional)                                                          | string                 | The receipt identifier of the revenue.                                                                             | ""      |
| ReceiptSig (optional)                                                       | string                 | The receipt signature of the revenue.                                                                              | ""      |
| Properties (optional)                                                       | map[string]interface{} | An map of event properties to include in the revenue event.                                                        | nil     |
| Revenue (optional)                                                          | float64                | Use negative values to indicate refunds. `Revenue = Quantity * Price `                                             | 0       |

## Flush

The `Flush` method triggers the client to send buffered events.

```Go
client.Flush()
```

## Shutdown

The `Shutdown` method closes the Client `struct`. A closed Client `struct` doesn't accept new events and tries to flush events in the buffer. Then the Client `struct` shuts down running threads.

```Go
client.Shutdown()
```

## Plugins

Plugins let you extend the Amplitude SDK's behavior. For example, you can modify event properties (enrichment type) or send events to third-party APIs (destination type). A plugin is a struct with `Setup()` and `Execute()` methods.

### Client.Add

The `Add` method adds a plugin to the Amplitude Client `struct`. Plugins can help process and send events.

```Go
client.Add(pluginObj)
```

### Client.Remove

The `Remove` method removes the given plugin from the Client `struct` if it exists.

```Go
client.Remove(pluginName)
```

### Plugin.Setup

This method contains logic that prepares the plugin for use and takes a `Config` struct as a parameter. The expected return value is `nil`. A typical use for this method is to copy configuration from `Config` or instantiate plugin dependencies. The SDK calls this method when you register the plugin to the client through `client.Add()`.

### Plugin.Execute

This method contains the logic for processing events and takes `*Event` as a parameter. If you use the plugin as an enrichment type plugin, the expected return value is the modified or enriched event. If you use the plugin as a destination type plugin, the expected return value is a map with keys: `event` (BaseEvent), `code` (number), and `message` (string). The SDK calls this method for each event instrumented using the client interface, including Identify, GroupIdentify, and Revenue events.

## Plugin examples

### Enrichment type plugin

Here's an example of a plugin that modifies each instrumented event by adding an increment integer to the `EventID` property of an event.

```Go
package main

import "github.com/amplitude/analytics-go/amplitude"

type addEventIDPlugin struct {
    currentID int
    config    amplitude.Config
}

func (plugin *addEventIDPlugin) Name() string {
    return "AddEventId"
}

func (plugin *addEventIDPlugin) Setup(config amplitude.Config) {
    plugin.config = config
}

func (plugin *addEventIDPlugin) Type() amplitude.PluginType {
    return amplitude.PluginTypeEnrichment
}

func (plugin *addEventIDPlugin) Execute(event *amplitude.Event) *amplitude.Event {
    event.EventID = plugin.currentID
    plugin.currentID += 1
    return event
}

func main() {
    config := amplitude.NewConfig(AMPLITUDE_API_KEY)
    client := amplitude.NewClient(config)
    defer client.Shutdown()

    client.Add(&addEventIDPlugin{})
}
```

### Destination type plugin

Here's an example of a plugin that sends each instrumented event to a target server URL.

```Go
package main

import (
    "bytes"
    "encoding/json"
    "net/http"

    "github.com/amplitude/analytics-go/amplitude"
)

type myDestinationPlugin struct {
    url        string
    config     amplitude.Config
    httpClient http.Client
}

func (plugin *myDestinationPlugin) Name() string {
    return "MyDestinationPlugin"
}

// Setup is called on plugin installation
func (plugin *myDestinationPlugin) Setup(config amplitude.Config) {
    plugin.config = config
    plugin.httpClient = http.Client{}
}

// Type defines your amplitude.PluginType from:
//  - amplitude.PluginTypeBefore
//  - amplitude.PluginTypeEnrichment
//  - amplitude.PluginTypeDestination
func (plugin *myDestinationPlugin) Type() amplitude.PluginType {
    return amplitude.PluginTypeDestination
}

// Execute is called on each event instrumented
func (plugin *myDestinationPlugin) Execute(event *amplitude.Event) {
    payload := map[string]interface{}{"key": "secret", "events": event}
    payloadBytes, err := json.Marshal(payload)

    if err != nil {
        plugin.config.Logger.Errorf("Event encoding failed: ", err)
    }

    request, err := http.NewRequest("POST", plugin.url, bytes.NewReader(payloadBytes))
    if err != nil {
        plugin.config.Logger.Errorf("Building new request failed", err)
    }

    response, err := plugin.httpClient.Do(request)
    if err != nil {
        plugin.config.Logger.Errorf("HTTP request failed", err)
    } else {
        defer response.Body.Close()
    }
}

func main() {
    config := amplitude.NewConfig(AMPLITUDE_API_KEY)
    client := amplitude.NewClient(config)
    defer client.Shutdown()

    client.Add(&myDestinationPlugin{
        // Change it to your target server URL
        url: "https://custom.domain.com",
    })

    client.Track(amplitude.Event{
        UserID: "user-id",
        EventType: "Button Clicked",
    })
}
```

The previous example sends an HTTP POST request with a body in JSON format:

```json
{
  "events": {
    "event_type": "Button Clicked",
    "user_id": "user-id",
    "time": 1660683660056,
    "insert_id": "1c8aac41-8257-4bea-ab3f-de914e39df5e",
    "library": "amplitude-go/0.0.2",
    "plan": {}
  },
  "key": "secret"
}
```
