Analytics for Go

Community x
Maintenance ✓
Flagship x
?

Maintenance libraries send data as intended but receive no new feature support and only critical maintenance updates from Segment. When possible, Segment recommends using a Flagship version of these libraries.


Current Version: v3.3.0

Release Date: Oct 31, 2023

Segment’s Go library lets you record analytics data from your Go code. The requests hit Segment servers, and then Segment routes your data to any analytics service you enable on your destinations page.

This library is open-source, so you can check it out on GitHub.

All of Segment’s server-side libraries are built for high-performance, so you can use them in your web server controller code. This library uses a tunable buffer to batch messages, optimized for throughput and reduced network activity.

Getting Started

Install analytics-go using go get:

go get gopkg.in/segmentio/analytics-go.v3

Then import it and initialize an instance with your source’s Write Key. Of course, you’ll want to replace YOUR_WRITE_KEY with your actual Write Key which you can find in Segment under your source settings.

package main

import "gopkg.in/segmentio/analytics-go.v3"

func main() {
  client := analytics.New("YOUR_WRITE_KEY")
  defer client.Close()

  // Use the client.
}

That will create a client that you can use to send data to Segment for your source.

The default initialization settings are production-ready and queue 20 messages before sending a batch request, and a 5 second interval.

Regional configuration

For Business plans with access to Regional Segment, you can use the host configuration parameter to send data to the desired region:

Oregon (Default) — api.segment.io/ Dublin — events.eu1.segmentapis.com

Identify

Good to know: For any of the different methods described on this page, you can replace the properties and traits in the code samples with variables that represent the data collected.

Identify lets you tie a user to their actions and record traits about them. It includes a unique User ID and any optional traits you know about them.

Segment recommends calling Identify a single time when the user’s account is first created, and only identifying again later when their traits change.

Example Identify call:

client.Enqueue(analytics.Identify{
  UserId: "019mr8mf4r",
  Traits: analytics.NewTraits().
    SetName("Michael Bolton").
    SetEmail("mbolton@example.com").
    Set("plan", "Enterprise").
    Set("friends", 42),
})

This call is identifying Michael by his unique User ID (the one you know him by in your database) and labeling him with name, email, plan and friends traits.

The Identify call has the following fields:

userId String The ID for this user in your database.
traits Traits, optional A dictionary of traits you know about the user. Things like: email, name or friends.

Find details on the identify method payload in the Segment Spec.

Track

Track lets you record the actions your users perform.Every action triggers what Segment calls an “event”, which can also have associated properties.

You’ll want to track events that are indicators of success for your site, like Signed Up, Item Purchased or Article Bookmarked.

To get started, Segment recommends tracking just a few important events. You can always add more later.

Example Track call:

client.Enqueue(analytics.Track{
  UserId: "f4ca124298",
  Event:  "Signed Up",
  Properties: analytics.NewProperties().
    Set("plan", "Enterprise"),
})

This example Track call tells you that your user just triggered the Signed Up event choosing the “Enterprise” plan.

Track event properties can be anything you want to record. In this case, plan type.

The Track call has the following fields:

event String The name of the event you’re tracking. Segment recommends human-readable names like Song Played or Status Updated.
properties Properties, optional A dictionary of properties for the event. If the event was Product Added, it might have properties like price or product.

Find details on best practices in event naming as well as the Track method payload in the Segment Spec.

Page

The Page method lets you record page views on your website, along with optional extra information about the page being viewed.

If you’re using Segment’s client-side set up in combination with the Go library, page calls are already tracked for you by default. However, if you want to record your own page views manually and aren’t using the client-side library, read on.

Example Page call:

client.Enqueue(analytics.Page{
  UserId: "f4ca124298",
  Name:   "Go Library",
  Properties: analytics.NewProperties().
    SetURL("https://segment.com/libraries/go/"),
})

The Page call has the following fields:

name String The webpage name you’re tracking. Segment recommends human-readable names like Login or Register.
properties Properties, optional A dictionary of properties for the page visit. If the page was Login, it might have properties like path or title.

Find details on the Page payload in the Segment Spec.

Group

Group lets you associate an identified user with a group. A group could be a company, organization, account, project or team. It also lets you record custom traits about the group, like industry or number of employees.

This is useful for tools like Intercom, Preact and Totango, as it ties the user to a group of other users.

Example Group call:

client.Enqueue(analytics.Group{
  UserId:  "019mr8mf4r",
  GroupId: "56",
  Traits: map[string]interface{}{
    "name":        "Initech",
    "description": "Accounting Software",
  },
})

The Group call has the following fields:

groupId String The ID for this group in your database.
traits Traits, optional A dictionary of traits you know about the group. Things like: name or website.

Find more details about Group, including the Group payload, in the Segment Spec.

Alias

Alias is how you associate one identity with another. This is an advanced method, but it is required to manage user identities successfully in some destinations.

In Mixpanel it’s used to associate an anonymous user with an identified user once they sign up. For Kissmetrics, if your user switches IDs, you can use ‘alias’ to rename the ‘userId’.

Example Alias call:

client.Enqueue(analytics.Alias{
  PreviousId: "anonymousUser",
  UserId:     "019mr8mf4r",
})

The Alias call has the following fields:

UserId string The ID for this user in your database.
PreviousId string The previous ID to alias from.

Here’s a full example of how you might use the Alias call:

// the anonymous user does actions ...
client.Enqueue(analytics.Track{
  Event:  "Anonymous Event",
  UserId: anonymousUser,
})

// the anonymous user signs up and is aliased
client.Enqueue(analytics.Alias{
  PreviousId: anonymousUser,
  UserId:     "019mr8mf4r",
})

// the identified user is identified
client.Enqueue(analytics.Identify{
  UserId: "019mr8mf4r",
  Traits: map[string]interface{}{
    "name":    "Michael Bolton",
    "email":   "mbolton@example.com",
    "plan":    "Enterprise",
    "friends": 42,
  },
})

// the identified user does actions ...
client.Enqueue(analytics.Track{
  Event:      "Item Viewed",
  UserId:     "019mr8mf4r",
  Properties: map[string]interface{}{
    "item": "lamp",
  },
})

For more details about Alias, including the Alias call payload, check out the Segment Spec.


Development Settings

You can use the BatchSize field of your configuration to 1 during development to make the library flush every time a message is submitted, so that you can be sure your calls are working properly.

func main() {
  client, _ := analytics.NewWithConfig("YOUR_WRITE_KEY", analytics.Config{
		BatchSize: 1,
	})
}

Logging

The Verbose field of your configuration controls the level of logging, while the Logger field provides a hook to capture the log output:

func main() {
  client, _ := analytics.NewWithConfig("YOUR_WRITE_KEY", analytics.Config{
		Verbose: true,
		Logger:  analytics.StdLogger(log.New(os.Stderr, "segment ", log.LstdFlags)),
	})
}

Selecting Destinations

The Alias, Group, Identify, Page, and Track calls can all be passed an object of context.integrations that lets you turn certain integrations on or off. By default all destinations are enabled.

Here’s an example Track call with the context.integrations object shown.

client.Enqueue(analytics.Track{
  Event:  "Membership Upgraded",
  UserId: "019mr8mf4r",
  Integrations: map[string]interface{}{
    "All":      false,
    "Mixpanel": true,
  },
})

In this case, you’re specifying that you want this Track to only go to Mixpanel. All: false says that no destination should be enabled unless otherwise specified, and Mixpanel: true turns on Mixpanel.

Destination flags are case sensitive and match the destination’s name in the docs (for example, “AdLearn Open Platform”, “awe.sm”, or “MailChimp”).

Note:

  • Business Tier users can filter Track calls right from the Segment UI on your source schema page. Segment recommends using the UI if possible since it’s a much simpler way of managing your filters and can be updated with no code changes on your side.

  • If you are on a grandfathered plan, events sent server-side that are filtered through the Segment dashboard still count towards your API usage.

Historical Import

You can import historical data by adding the timestamp argument to any of your method calls. This can be helpful if you’ve just switched to Segment.

Historical imports can only be done into destinations that can accept historical timestamped data. Most analytics tools like Mixpanel, Amplitude, Kissmetrics, etc. can handle that type of data just fine. One common destination that does not accept historical data is Google Analytics since their API cannot accept historical data.

Note: If you’re tracking things that are happening right now, leave out the timestamp and Segment’s servers will timestamp the requests for you.

Context

You can send Context fields in two ways with the Go library.

Firstly, you can set a global context field that will be set on all messages from the client.

client, _ := analytics.NewWithConfig("h97jamjwbh", analytics.Config{
  DefaultContext: &analytics.Context{
    App: analytics.AppInfo{
      Name:    "myapp",
      Version: "myappversion",
    },
  },
})

Secondly, you can set a context field on specific events.

client.Enqueue(analytics.Identify{
        UserId: "019mr8mf4r",
        Traits: analytics.NewTraits().
            Set("friends", 42),
        Context: &analytics.Context{
            Extra: map[string]interface{}{
                "active": true,
            },
        },
})

Note that any custom fields must be set under the Extra field. They will automatically be inlined into the serialized context structure. For instance, the Identify call above would be serialized to:

{
  "type": "identify",
  "userId": "019mr8mf4r",
  "traits": {
    "friends": 42,
  },
  "context": {
    "active": true,
    "library": {
      "name": "analytics-go",
      "version": "3.0.0"
    }
  }
}

Batching

Segment’s libraries are built to support high performance environments. That means it is safe to use analytics-go on a web server that’s serving hundreds of requests per second.

Every method you call does not result in an HTTP request, but is queued in memory instead. Messages are flushed in batch in the background, which allows for much faster operation. If batch messages are not arriving in your debugger and no error is being thrown you may want to slow the speed of your script down. This is because Segment runs a message batching loop in a go-routine so if the script runs too fast it won’t execute on the network calls before it exits the loop.

By default, Segment’s library will flush:

  • every 20 messages (control with FlushAt)
  • if 5 seconds has passed since the last flush (control with FlushAfter)

There is a maximum of 500KB per batch request and 32KB per call.

HTTP Tracking API limits

Segment's HTTP Tracking API accepts batch requests up to 500KB. To avoid errors in event creation, ensure that individual event payload sizes remain below 32KB.

Sometimes you might not want batching (eg. when debugging, or in short-lived programs). You can turn off batching by setting the FlushAt argument to 1, and your requests will always be sent right away.

Options

If you hate defaults you can configure analytics-go has a lot of configuration options. You can read more in the Godocs.

Version 2 (Deprecated)

If you’re looking for documentation for the v2 version of the library, see Segment’s Go v2 documentation.

Migrating from v2

v3 is a rewrite of the v2 version of the Go Library. Segment recommends using v3 as it supports many new features, has significant design improvements and is better tested.

v3 is currently in the v3.0 branch to minimize breaking changes for customers not using a package manager. You can refer to the documentation for your package manager to see how to use the v3.0 branch.

for example, with govendor, you would run the command:

govendor fetch github.com/segmentio/analytics-go@v3.0

Alternatively, you can also use gopkg.in. First run go get gopkg.in/segmentio/analytics-go.v3 and replace your imports with import "gopkg.in/segmentio/analytics-go.v3".

To help with migrating your code, Segment recommends checking out a simple example that is written in v2 and v3 so you can easily see the differences.

The first difference you’ll notice is that Client is now an interface. It has a single method - Enqueue that can accept messages of all types.

track := analytics.Track{
  Event:  "Download",
  UserId: "123456",
  Properties: map[string]interface{}{
    "application": "Segment Desktop",
    "version":     "1.1.0",
    "platform":    "osx",
  },
}

// in v2, you would call the `Track` method with a `Track` struct.
client.Track(&track)

// in v3, you would call the `Enqueue` method with a `Track` struct.
// Note that a pointer is not used here.
client.Enqueue(track)

Secondly, you’ll notice that there are new types such as analytics.Properties and analytics.Traits. These can be used to replace map[string]interface{}. They provide type safety and reduce the chance of accidentally sending fields that are named incorrectly.

For instance, the following two examples are functionally equivalent in v3.

client.Enqueue(analytics.Track{
  UserId: "f4ca124298",
  Event:  "Signed Up",
  Properties: analytics.NewProperties().
    SetCategory("Enterprise").
    Set("application", "Segment Desktop"),
})
client.Enqueue(analytics.Track{
  UserId: "f4ca124298",
  Event:  "Signed Up",
  Properties: map[string]interface{}{
    "category": "Segment Desktop",
    "application": "Segment Desktop",
  },
})

Lastly, you’ll notice that configuration is provided during initialization and cannot be changed after initialization. The various configuration options are documented in the GoDocs.

These are examples of applying same configuration options in v2 and v3.

// Example in v2:
client := analytics.New("h97jamjwbh")
client.Interval = 30 * time.Second
client.Verbose = true
client.Size = 100

// Example in v3:
client, _ := analytics.NewWithConfig("h97jamjwbh", analytics.Config{
  Interval:  30 * time.Second,
  BatchSize: 100,
  Verbose:   true,
})

What’s new in v3

v3 is a rewrite of Segment’s v2 version of the Go Library with many new features.

  • New type safe API to set properties, traits and context fields. This is less error prone than using the map[string]interface{} type (though you can still do so).
client.Enqueue(analytics.Track{
  UserId: "f4ca124298",
  Event:  "Signed Up",
  Properties: analytics.NewProperties().
    SetCategory("Enterprise"),
    SetCoupon("synapse"),
    SetDiscount(10),
})
  • Dynamically split batches into appropriately sized chunks to meet Segment’s API size limits. Previously you would have to calculate the batch size depending on this size of your data to figure out the appropriate size.

  • Improved logging abstraction. Previously Segment relied solely on the standard library log.Logger type which cannot distinguish between error and non-error logs. v3 has it’s own Logger interface that can be used to capture errors for your own reporting purposes. An adapter for the standard library logger is also included.

  • Ability to configure the retry policy based on the number of attempts.

client, _ := analytics.NewWithConfig("h97jamjwbh", analytics.Config{
  RetryAfter: func(attempt int) time.Duration {
    return time.Duration(attempt * 10)
  },
})
  • Configurable default context on all messages.
client, _ := analytics.NewWithConfig("h97jamjwbh", analytics.Config{
  DefaultContext: &analytics.Context{
    App: analytics.AppInfo{
      Name:    "myapp",
      Version: "myappversion",
    },
  },
})

Troubleshooting

The following tips often help resolve common issues.

No events in my debugger

  1. Double check that you’ve followed all the steps in the Quickstart.

  2. Make sure that you’re calling a Segment API method once the library is successfully installed—identify, track, etc.

  3. Make sure your application isn’t shutting down before the Analytics.Client local queue events are pushed to Segment. You can manually call Analytics.Client.Flush() to ensure the queue is fully processed before shutdown.

Other common errors

If you are experiencing data loss from your Go source, you may be experiencing one or more of the following common errors:

  • Payload is too large: If you attempt to send events larger than 32KB per normal API request or batches of events larger than 500KB per request, Segment’s tracking API responds with 400 Bad Request. Try sending smaller events (or smaller batches) to correct this error.

  • Identifier is not present: Segment’s tracking API requires that each payload has a userId and/or anonymousId. If you send events without either the userId or anonymousId, Segment’s tracking API responds with an no_user_anon_id error. Check the event payload and client instrumentation for more details.

  • Track event is missing name: All Track events to Segment must have a name in string format.

  • Event dropped during deduplication: Segment automatically adds a messageId field to all payloads and uses this value to deduplicate events. If you’re manually setting a messageId value, ensure that each event has a unique value.

  • Incorrect credentials: Double check your credentials for your downstream destination(s).

  • Destination incompatibility: Make sure that the destination you are troubleshooting can accept server-side API calls. You can see compatibility information on the Destination comparison by category page and in the documentation for your specific destination.

  • Destination-specific requirements: Check out the destination’s documentation to see if there are other requirements for using the method and destination that you’re trying to get working.

This page was last modified: 30 May 2024



Get started with Segment

Segment is the easiest way to integrate your websites & mobile apps data to over 300 analytics and growth tools.
or
Create free account