{"id":21414684,"url":"https://github.com/customerio/go-customerio","last_synced_at":"2025-10-04T18:09:32.782Z","repository":{"id":25705334,"uuid":"29141982","full_name":"customerio/go-customerio","owner":"customerio","description":"Official Golang client for the Customer.io API","archived":false,"fork":false,"pushed_at":"2025-06-13T20:17:48.000Z","size":75,"stargazers_count":27,"open_issues_count":8,"forks_count":23,"subscribers_count":36,"default_branch":"main","last_synced_at":"2025-07-10T05:36:23.226Z","etag":null,"topics":["customerio","go"],"latest_commit_sha":null,"homepage":"https://customer.io/docs/api/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/customerio.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2015-01-12T15:32:26.000Z","updated_at":"2025-06-13T20:11:43.000Z","dependencies_parsed_at":"2024-06-18T18:24:02.508Z","dependency_job_id":"7da9c817-46dd-4294-b0fc-162186336985","html_url":"https://github.com/customerio/go-customerio","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/customerio/go-customerio","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/customerio%2Fgo-customerio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/customerio%2Fgo-customerio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/customerio%2Fgo-customerio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/customerio%2Fgo-customerio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/customerio","download_url":"https://codeload.github.com/customerio/go-customerio/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/customerio%2Fgo-customerio/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265240067,"owners_count":23732934,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["customerio","go"],"created_at":"2024-11-22T18:32:36.478Z","updated_at":"2025-10-04T18:09:27.723Z","avatar_url":"https://github.com/customerio.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=center\u003e\n  \u003ca href=\"https://customer.io\"\u003e\n    \u003cimg src=\"https://avatars.githubusercontent.com/u/1152079?s=200\u0026v=4\" height=\"60\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n![Latest release](https://img.shields.io/github/v/release/customerio/go-customerio)\n![Software License](https://img.shields.io/github/license/customerio/go-customerio)\n[![CI status](https://github.com/customerio/go-customerio/actions/workflows/main.yml/badge.svg)](https://github.com/customerio/go-customerio/actions/workflows/main.yml)\n![Go version](https://img.shields.io/github/go-mod/go-version/customerio/go-customerio)\n[![Go Doc](https://img.shields.io/badge/Go_Doc-reference-blue.svg)](https://pkg.go.dev/github.com/customerio/go-customerio/v3)\n\n# Customer.io Journeys Go Client \n\nA Go client library for the [Customer.io Journeys Track API](https://customer.io/docs/api/track). If you're new to Customer.io, we recommend that you integrate with our [Data Pipelines Go client](https://github.com/customerio/cdp-analytics-go) instead.\n\n## Installation\n\nAdd this line to your application's imports:\n\n```go\nimport (\n    // ...\n    \"github.com/customerio/go-customerio/v3\"\n)\n```\n\nAnd then execute:\n\n    go get\n\nOr install it yourself:\n\n    $ go get github.com/customerio/go-customerio/v3\n\n## Before we get started: API client vs. JavaScript snippet\n\nIt's helpful to know that everything below can also be accomplished\nthrough the [Customer.io JavaScript snippet](https://customer.io/docs/basic-integration.html).\n\nIn many cases, using the JavaScript snippet will be easier to integrate with\nyour app, but there are several reasons why using the API client is useful:\n\n- You're not planning on triggering emails based on how customers interact with\n  your website (e.g. users who haven't visited the site in X days)\n- You're using the JavaScript snippet, but have a few events you'd like to\n  send from your backend system. They will work well together!\n- You'd rather not have another JavaScript snippet slowing down your frontend.\n  Our snippet is asynchronous (doesn't affect initial page load) and very small, but we understand.\n\nIn the end, the decision on whether or not to use the API client or\nthe JavaScript snippet should be based on what works best for you.\nYou'll be able to integrate **fully** with [Customer.io](https://customer.io) with either approach.\n\nCreate an instance of the Track API or App API client with your [Customer.io credentials](https://fly.customer.io/settings/api_credentials).\n\n## Usage\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"log\"\n\t\"time\"\n\n\t\"github.com/customerio/go-customerio/v3\"\n)\n\nvar (\n\t// You can find or create new API credentials in your Customer.io\n\t// account under \"Account Settings\" =\u003e \"API Credentials\":\n\t// (https://fly.customer.io/settings/api_credentials)\n\tsiteID      string = \"your-site-id\"\n\ttrackAPIKey string = \"your-track-api-key\"\n\tappAPIKey   string = \"your-app-api-key\"\n)\n\nfunc main() {\n\t// Create an instance of the Customer.io Track API client\n\ttrack := customerio.NewTrackClient(siteID, trackAPIKey, customerio.WithRegion(customerio.RegionUS))\n\n\t// Send an Identify TrackAPI call\n\tif err := track.Identify(\"5\", map[string]interface{}{\n\t\t\"email\":      \"lucy@example.com\",\n\t\t\"created_at\": time.Now().Unix(),\n\t\t\"first_name\": \"Lucy\",\n\t\t\"plan\":       \"basic\",\n\t}); err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\t// Create an instance of the Customer.io App API Client\n\tcio := customerio.NewAPIClient(appAPIKey, customerio.WithRegion(customerio.RegionUS))\n\n\tctx, cancel := context.WithTimeout(context.Background(), time.Second*10)\n\tdefer cancel()\n\n\t// The request object allows you to specify recipients and message data\n\trequest := customerio.SendEmailRequest{\n\t\tIdentifiers: map[string]string{\n\t\t\t\"id\": \"customer_1\",\n\t\t},\n\t\tTo:      \"customer@example.com\",\n\t\tFrom:    \"business@example.com\",\n\t\tSubject: \"hello, {{ trigger.name }}\",\n\t\tBody:    \"hello from the Customer.io {{ trigger.client }} client\",\n\t\tMessageData: map[string]interface{}{\n\t\t\t\"client\": \"Go\",\n\t\t\t\"name\":   \"gopher\",\n\t\t},\n\t}\n\n\t// Send the email with a 10 second timeout\n\tresp, err := cio.SendEmail(ctx, \u0026request)\n\tif err != nil {\n\t\tlog.Fatal(err)\n\t}\n\n\tfmt.Printf(\"Resp: %s\\n\", resp)\n}\n\n```\n\nYour account region (`customerio.RegionUS` or `customerio.RegionEU`) is optional. If you do not specify your region, we assume that your account is based in the US (`customerio.RegionUS`). \n\nIf your account is based in the EU and you do not provide the correct region, we'll route requests from the US to `customerio.RegionEU` accordingly, however this may cause data to be logged in the US. \n\n### Identify logged in customers\n\nTracking data of logged in customers is a key part of [Customer.io](https://customer.io). In order to send triggered messages, we must know the email address of the customer to send email or the phone number for SMS.\n\nYou can also specify any number of customer attributes which help tailor [Customer.io](https://customer.io) to your business.\n\nAttributes you specify are useful in several ways:\n\n- As customer variables in your triggered messages. For instance, if you specify the customer's name, you can personalize the triggered message by using it in the subject or body.\n\n- As a way to filter who should receive a triggered message. For instance, if you pass along the current subscription plan (free / basic / premium) for your customers, you can set up triggers which are only sent to customers who have subscribed to a particular plan (e.g. \"premium\").\n\nYou'll want to identify your customers when they sign up for your product and any time their key information changes. This keeps [Customer.io](https://customer.io) up to date with your customer information.\n\n```go\n// Arguments\n// customerID (required) - a unique identifier string for this customers\n// attributes (required) - a ```map[string]interface{}``` of information about the customer. You can pass any\n//                         information that would be useful in your triggers. You\n//                         should at least pass in an email, and created_at timestamp.\n//                         your interface{} should be parseable as JSON by 'encoding/json'.Marshal\n\nif err := track.Identify(\"5\", map[string]interface{}{\n  \"email\": \"bob@example.com\",\n  \"created_at\": time.Now().Unix(),\n  \"first_name\": \"Bob\",\n  \"plan\": \"basic\",\n}); err != nil {\n  // handle error\n}\n```\n\n### Deleting customers\n\nDeleting a customer will remove them, and all their information from\nCustomer.io. Note: if you're still sending data to Customer.io via\nother means (such as the javascript snippet), the customer could be\nrecreated.\n\n```go\n// Arguments\n// customerID (required) - a unique identifier for the customer.  This\n//                          should be the same id you'd pass into the\n//                          `identify` command above.\n\nif err := track.Delete(\"5\"); err != nil {\n  // handle error\n}\n```\n\n### Merge Duplicate Customers\n\nWhen you merge two people, you pick a primary person and merge a secondary, duplicate person into the primary person. The primary person remains after the merge and the secondary person is deleted. This process is permanent: you cannot recover the secondary person.\n\nThe first and third parameters represent the identifier for the primary and secondary people respectively, one of `id`, `email`, or `cio_id`. The second and fourth parameters are the identifier values for the primary and secondary people, respectively.\n\n```go\nif err := track.MergeCustomers(customerio.IdentifierTypeEmail, \"cool.person@company.com\", customerio.IdentifierTypeCioID, \"C123\"); err != nil {\n  // handle error\n}\n```\n\n### Tracking a custom event\n\nNow that you're identifying your customers with [Customer.io](https://customer.io), you can now send events like \"purchased\" or \"watchedIntroVideo\". \n\nThese allow you to more specifically target your users with automated messages, and track conversions when you're sending automated messages to encourage your customers to perform an action.\n\n```go\n// Arguments\n// customerID (required)  - the id of the customer who you want to associate with the event.\n// name (required)        - the name of the event you want to track.\n// attributes (optional)  - any related information you'd like to attach to this\n//                          event, as a ```map[string]interface{}```. \n//                          These attributes can be used in your triggers to control who should\n//                          receive the triggered message. You can set any number of data values.\n\nif err := track.Track(\"5\", \"purchase\", map[string]interface{}{\n    \"type\": \"socks\",\n    \"price\": \"13.99\",\n}); err != nil {\n  // handle error\n}\n```\n\n### Tracking an anonymous event\n\nYou can also send anonymous events representing people you haven't identified. An anonymous event requires an `anonymous_id` representing the unknown person and an event `name`. When you identify a person, you can set their `anonymous_id` attribute. If [event merging](https://customer.io/docs/anonymous-events/#turn-on-merging) is turned on in your workspace, and the attribute matches the `anonymous_id` in one or more events that were logged within the last 30 days, we associate those events with the person.\n\n```go\n// Arguments\n// anonymous_id (required)    - nullable, an identifier representing an unknown person.\n// name (required)            - the name of the event you want to track.\n// attributes (optional)      - any related information you'd like to attach to this\n//                              event, as a ```map[string]interface{}```. \n//                              These attributes can be used in your triggers to control who should\n//                              receive the triggered message. You can set any number of data values.\n\nif err := track.TrackAnonymous(\"anonymous_id\", \"invite\", map[string]interface{}{\n    \"first_name\": \"Alex\",\n    \"source\": \"OldApp\",\n}); err != nil {\n  // handle error\n}\n```\n#### Anonymous invite events\n\nIf you previously sent [invite events](https://customer.io/docs/anonymous-invite-emails/), you can achieve the same functionality by sending an anonymous event an empty string for the anonymous identifier. To send anonymous invites, your event *must* include a `recipient` attribute. \n\n```go\nif err := track.TrackAnonymous(\"\", \"invite\", map[string]interface{}{\n    \"first_name\": \"Alex\",\n    \"recipient\": \"alex.person@example.com\",\n}); err != nil {\n  // handle error\n}\n```\n\n### Adding a device to a customer\n\nIn order to send push notifications, we need customer device information.\n\n```go\n// Arguments\n// customerID (required) - a unique identifier string for this customer\n// deviceID (required)   - a unique identifier string for this device\n// platform (required)   - the platform of the device, currently only accepts 'ios' and 'android'\n// data (optional)       - a ```map[string]interface{}``` of information about the device. \n//                         You can pass any key/value pairs that would be useful in your triggers. \n//                         Your interface{} should be parseable as Json by 'encoding/json'.Marshal\n\nif err := track.AddDevice(\"5\", \"messaging token\", \"android\", map[string]interface{}{\n\"last_used\": time.Now().Unix(),\n\"attribute_name\": \"attribute_value\",\n}); err != nil {\n  // handle error\n}\n```\n\n### Deleting devices\n\nDeleting a device will remove it from the customer's device list in Customer.io.\n\n```go\n// Arguments\n// customerID (required)  - the id of the customer the device you want to delete belongs to\n// deviceToken (required) - a unique identifier for the device.\n//                          This should be the same id you'd pass into the\n//                          `addDevice` command above\n\nif err := track.DeleteDevice(\"5\", \"messaging-token\"); err != nil {\n  // handle error\n}\n```\n\n### Send Transactional Messages\n\nTo use the Customer.io [Transactional API](https://customer.io/docs/transactional-api), create an instance of the API client using an [App API key](https://customer.io/docs/managing-credentials#app-api-keys).\n\n## Email\nCreate a `customerio.SendEmailRequest` instance, and then use `(c *customerio.APIClient).SendEmail` to send your message. [Learn more about transactional messages and optional `SendEmailRequest` properties](https://customer.io/docs/transactional-api).\n\nYou can also send attachments with your message. Use `customerio.SendEmailRequest.Attach` to encode attachments.\n\n```go\nclient := customerio.NewAPIClient(\"\u003cextapikey\u003e\", customerio.WithRegion(customerio.RegionUS));\n\n// TransactionalMessageId — the ID of the transactional message you want to send.\n// To                     — the email address of your recipients.\n// Identifiers            — contains the id of your recipient. \n//                          If the id does not exist, Customer.io creates it.\n// MessageData            — contains properties that you want reference in your message using liquid.\n// Attach                 — a helper that encodes attachments to your message.\n\nrequest := customerio.SendEmailRequest{\n  To: \"person@example.com\",\n  TransactionalMessageID: \"3\",\n  MessageData: map[string]interface{}{\n    \"name\": \"Person\",\n    \"items\": map[string]interface{}{\n      \"name\": \"shoes\",\n      \"price\": \"59.99\",\n    },\n    \"products\": []interface{}{},\n  },\n  Identifiers: map[string]string{\n    \"id\": \"example1\",\n  },\n}\n\n// (optional) attach a file to your message.\nf, err := os.Open(\"receipt.pdf\")\nif err != nil {\n  // handle error\n}\ndefer f.Close()\n\nrequest.Attach(\"receipt.pdf\", f)\n\nbody, err := client.SendEmail(context.Background(), \u0026request)\nif err != nil {\n  // handle error\n}\n\nfmt.Println(body)\n```\n\n## Push\nCreate a `customerio.SendPushRequest` instance, and then use `(c *customerio.APIClient).SendPush` to send your message. [Learn more about transactional messages and optional `SendPush` properties](https://customer.io/docs/transactional-api).\n\n```go\nclient := customerio.NewAPIClient(\"\u003cextapikey\u003e\", customerio.WithRegion(customerio.RegionUS));\n\nrequest := customerio.SendPushRequest{\n  TransactionalMessageID: \"3\",\n  MessageData: map[string]interface{}{\n    \"name\": \"Person\",\n    \"items\": map[string]interface{}{\n      \"name\": \"shoes\",\n      \"price\": \"59.99\",\n    },\n    \"products\": []interface{}{},\n  },\n  Identifiers: map[string]string{\n    \"id\": \"example1\",\n  },\n}\n\n// (optional) upsert a particular device for the profile the push is being sent to.\ndevice, err := customerio.NewDevice(\"device-id\", \"android\", map[string]interface{}{\"optional_attr\": \"value\"})\nif err != nil {\n  // handle error, invalid device params.\n}\nrequest.Device = device\n\nbody, err := client.SendPush(context.Background(), \u0026request)\nif err != nil {\n  // handle error\n}\n\nfmt.Println(body)\n```\n\n## Context Support\nThere are additional API methods that support passing a context that satisfies the `context.Context` interface to allow better control over dispatched requests. For example with sending an event:\n```go\n// Create an instance of the Customer.io Track API client\ntrack := customerio.NewTrackClient(siteID, trackAPIKey, customerio.WithRegion(customerio.RegionUS))\n\n// Create a context with a 5s deadline\nctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(5*time.Second))\ndefer cancel()\n\nif err := track.TrackCtx(ctx, \"5\", \"purchase\", map[string]interface{}{\n    \"type\": \"socks\",\n    \"price\": \"13.99\",\n}); err != nil {\n  // handle error\n}\n```\n\n## Contributing\n\n1. Fork it\n2. Clone your fork (`git clone git@github.com:MY_USERNAME/go-customerio.git \u0026\u0026 cd go-customerio`)\n3. Create your feature branch (`git checkout -b my-new-feature`)\n4. Commit your changes (`git commit -am 'feat: Added some feature'`)\n5. Push to the branch (`git push origin my-new-feature`)\n6. Create new Pull Request\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcustomerio%2Fgo-customerio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcustomerio%2Fgo-customerio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcustomerio%2Fgo-customerio/lists"}