Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 34 additions & 31 deletions src/protocols/apis-and-extensions/typewriter.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ redirect_from: '/protocols/typewriter/'
---

> warning ""
> Typewriter for analytics.js and analytics-node will receive no new features and only critical maintenance updates from Segment. Typewriter for other libraries and SDKs are not actively maintained by Segment. Typewriter is available on [GitHub](https://github.com/segmentio/typewriter/){:target="_blank”} under the MIT license for the open-source community to fork and contribute.
> Typewriter for Analytics.js and Analytics-Node will receive no new features and only critical maintenance updates from Segment. Typewriter for other libraries and SDKs are not actively maintained by Segment. Typewriter is available on [GitHub](https://github.com/segmentio/typewriter/){:target="_blank”} under the MIT license for the open-source community to fork and contribute.

[Typewriter](https://github.com/segmentio/typewriter){:target="_blank”} is a tool for generating strongly-typed Segment analytics libraries based on your pre-defined [Tracking Plan](/docs/protocols/tracking-plan) spec.

At a high-level, Typewriter can take an event from your Tracking Plan like this `"Order Completed"` event:

![Order Completed Event in a Protocols Tracking Plan](images/typewriter-order-completed.png)

Typewriter uses the event to generate a typed analytics call in different languages:
Typewriter uses the event to generate a typed Analytics call in different languages:

```ts
// Example client in your web app
Expand All @@ -34,9 +34,9 @@ SEGTypewriterAnalytics.orderCompleted(
> info ""
> Typewriter can generate clients for `analytics.js`, `analytics-node`, `analytics-swift` and `analytics-kotlin`.

These generated clients are embedded with metadata from your Tracking Plan, which contextualizes your analytics instrumentation, and reduces (or entirely eliminates!) incorrect instrumentations in your production environments. In your editor, you can access event names, descriptions, property names, types and more:
These generated clients are embedded with metadata from your Tracking Plan, which contextualizes your analytics instrumentation, and reduces (or entirely eliminates) incorrect instrumentations in your production environments. In your editor, you can access event names, descriptions, property names, types and more:

![Event name intellisense](images/typewriter-event-names.png)
![Event name intelli-sense](images/typewriter-event-names.png)

You can also configure Typewriter to validate analytic events at runtime, which can alert you to instrumentation errors during development and testing. Typewriter can warn you about missing required properties, invalid enum values, regex mismatches, and any other advanced [JSON Schema](https://json-schema.org/understanding-json-schema/) you configure in your Tracking Plan.

Expand All @@ -46,11 +46,11 @@ You can use this with a test suite to automatically fail your unit tests if the

![Example unit tests failing because of violations](images/typewriter-test-suite.png)

If you use a statically typed language (such as TypeScript, Java, Objective-C, or Swift), you get access to compile-time warnings about your instrumentation:
If you use a statically typed language (like TypeScript, Java, Objective-C, or Swift), you get access to compile-time warnings about your instrumentation:

![Example compile-time validation warnings](images/typewriter-compile-time-warnings.png)

Typewriter also helps teams adopt [analytics best practices](/docs/protocols/tracking-plan/best-practices/), such as avoiding autogenerated event names, and carefully considering what properties are tracked.
Typewriter also helps teams adopt [Analytics best practices](/docs/protocols/tracking-plan/best-practices/), like avoiding autogenerated event names and carefully considering what properties are tracked.

To get started, check out one of the quickstart guides below:
- [Browser Quickstart](#browser-quickstart)
Expand All @@ -66,7 +66,7 @@ Have feedback on Typewriter? Consider opening a [GitHub Issue in the @segmentio/

## Prerequisites

Typewriter is built using [Node.js](https://nodejs.org/en/){:target="_blank”}, and requires node >= 14.x
Typewriter is built using [Node.js](https://nodejs.org/en/){:target="_blank”}, and requires node >= 14.x.

You can check if you have Node and NPM installed by running the following commands in your command-line window:

Expand All @@ -83,11 +83,11 @@ $ brew install node

Once you've installed Node and NPM, run the `--version` commands again to verify that they were installed correctly.

## Browser Quickstart
## Browser quickstart

To get started with Typewriter in your browser:
1. Make sure you have `node` installed using the instructions in the [prerequisites](#prerequisites) above.
2. Install `analytics.js` in your app. There are two methods.
1. Make sure you have `node` installed using the instructions in the [prerequisites](#prerequisites).
2. Install `analytics.js` in your app using one of the following methods:
- **Snippet method (most common)**: Paste the snippet in the[`Step 1: Copy the Snippet`](/docs/connections/sources/catalog/libraries/website/javascript/quickstart/#step-2-copy-the-segment-snippet) from the [`analytics.js` Quickstart Guide](/docs/connections/sources/catalog/libraries/website/javascript/quickstart/).
- **NPM method**: Load analytics.js with the npm library. Learn more about using the npm method in the [@segmentio/analytics-next](https://github.com/segmentio/analytics-next/tree/master/packages/browser#readme){:target="_blank”} repository.

Expand Down Expand Up @@ -138,7 +138,7 @@ To get started with Typewriter in your browser:
> info ""
> Run `npx typewriter` to regenerate your Typewriter client. You need to do this each time you update your Tracking Plan.

To help you minimize your bundle size, Typewriter supports [tree-shaking](https://webpack.js.org/guides/tree-shaking/){:target="_blank"} using named exports. All generated analytics calls generate and export automatically, so you can import them like so:
To help you minimize your bundle size, Typewriter supports [tree-shaking](https://webpack.js.org/guides/tree-shaking/){:target="_blank"} using named exports. All generated analytics calls generate and export automatically, so you can import them like this:

```ts
import { orderCompleted } from './analytics'
Expand All @@ -149,20 +149,20 @@ orderCompleted({
})
```

Typewriter wraps your analytics calls in an [ES6 `Proxy`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy){:target="_blank"}, which helps protect your application from crashing if you make analytics calls with a generated function that doesn't exist. For example, if an `Order Completed` event didn't exist in your Tracking Plan in the first example above, then your app would crash with a `TypeError: typewriter.orderCompleted is not a function`. However, since Typewriter dynamically proxies the underlying function calls, it can detect if a function doesn't exist, and handle it for you. Typewriter logs a warning message, then fires an `Unknown Analytics Call Fired` event into your source. This helps to prevent regressions when you migrate JavaScript projects to Typewriter in bulk. Keep in mind that proxying doesn't work with named exports.
Typewriter wraps your analytics calls in an [ES6 `Proxy`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy){:target="_blank"}, which helps protect your application from crashing if you make analytics calls with a generated function that doesn't exist. For example, if an `Order Completed` event didn't exist in your Tracking Plan in the first example above, then your app would crash with a `TypeError: typewriter.orderCompleted is not a function` error. However, since Typewriter dynamically proxies the underlying function calls, it can detect if a function doesn't exist, and handle it for you. Typewriter logs a warning message, then fires an `Unknown Analytics Call Fired` event into your source. This helps to prevent regressions when you migrate JavaScript projects to Typewriter in bulk. Keep in mind that proxying doesn't work with named exports.

## Node.js Quickstart
## Node.js quickstart

To get started with Node.js:
1. Make sure you have `node` installed using the instructions in the [prerequisites](#prerequisites) above.
1. Make sure you have `node` installed using the instructions in the [prerequisites](#prerequisites).
2. Install `@segment/analytics-node` in your app. For now, you just need to complete [`Step 2: Install the Module`](/docs/connections/sources/catalog/libraries/server/node/quickstart/#step-2-install-the-module) from the [`analytics-node` Quickstart Guide](/docs/connections/sources/catalog/libraries/server/node/quickstart).
3. Once you have `analytics-node` installed, add Typewriter as a developer dependency in your project:

```sh
$ npm install --save-dev typewriter
```

4. Run `npx typewriter init` to use the Typewriter quickstart wizard that generates a [`typewriter.yml`](#configuration-reference) configuration, along with your first Typewriter client. When you run the command, it creates a `typewriter.yml` file in your repo. For more information on the format of this file, see the [Typewriter Configuration Reference](#configuration-reference). The command also adds a new Typewriter client in `./analytics` (or whichever path you configured). You can import this client into your project, like so:
4. Run `npx typewriter init` to use the Typewriter quickstart wizard that generates a [`typewriter.yml`](#configuration-reference) configuration, along with your first Typewriter client. When you run the command, it creates a `typewriter.yml` file in your repository. For more information on the format of this file, see the [Typewriter Configuration Reference](#configuration-reference). The command also adds a new Typewriter client in `./analytics` (or whichever path you configured). You can import this client into your project, like so:

```ts
// Initialize analytics-node, per the analytics-node guide above.
Expand Down Expand Up @@ -193,15 +193,15 @@ To get started with Node.js:

Typewriter wraps your analytics calls in an [ES6 `Proxy`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy){:target="_blank”}, which helps protect your application from crashing if you make analytics calls with a generated function that doesn't exist. For example, if an `Order Completed` event didn't exist in your Tracking Plan in the first example above, then your app would crash with a `TypeError: typewriter.orderCompleted is not a function`. However, since `typewriter` dynamically proxies the underlying function calls, it can detect if a function does not exist, and handle it for you. Typewriter logs a warning message, then fires an `Unknown Analytics Call Fired` event into your source. This helps to prevent regressions when you migrate JavaScript projects to Typewriter in bulk. Keep in mind that proxying doesn't work with named exports.

## Swift Quickstart
## Swift quickstart

> info ""
> For use with the `analytics-ios` SDK, use [Typewriter v7](/docs/protocols/apis-and-extensions/typewriter-v7).

To get started using Typewriter with Swift:
1. Make sure you have `node` installed using the instructions in the [prerequisites](#prerequisites) above.
1. Make sure you have `node` installed using the instructions in the [prerequisites](#prerequisites).
2. Install `analytics-swift` in your app. Follow the [analytics-swift Quickstart Guide](/docs/connections/sources/catalog/libraries/mobile/swift).
3. Run `npx typewriter init` to use the Typewriter quickstart wizard that generates a [`typewriter.yml`](#configuration-reference) configuration, along with your first Typewriter client. When you run the command, it creates a `typewriter.yml` file in your repo. For more information on the format of this file, see the [Typewriter Configuration Reference](#configuration-reference).
3. Run `npx typewriter init` to use the Typewriter quickstart wizard that generates a [`typewriter.yml`](#configuration-reference) configuration, along with your first Typewriter client. When you run the command, it creates a `typewriter.yml` file in your repository. For more information on the format of this file, see the [Typewriter Configuration Reference](#configuration-reference).

<br> **Note:** Run `npx typewriter` to regenerate your Typewriter client. You need to do this each time you update your Tracking Plan.

Expand All @@ -216,15 +216,15 @@ To get started using Typewriter with Swift:
))
```

## Kotlin Quickstart
## Kotlin quickstart

> info ""
> For use with the `analytics-android` SDK, use [Typewriter v7](/docs/protocols/apis-and-extensions/typewriter-v7).

To get started using Typewriter with Kotlin:
1. Make sure you have `node` installed. Use the instructions in the [prerequisites](#prerequisites) above.
1. Make sure you have `node` installed. Use the instructions in the [prerequisites](#prerequisites).
2. Install `analytics-kotlin` in your app. Follow the [analytics-kotlin QuickStart Guide](/docs/connections/sources/catalog/libraries/mobile/kotlin-android/#getting-started).
3. Run `npx typewriter init`. This command enables you to use the Typewriter quickstart wizard that generates a [`typewriter.yml`](#configuration-reference) configuration, along with your first Typewriter client. The command creates a `typewriter.yml` file in your repo. For more information on the format of this file, see the [Typewriter Configuration Reference](#configuration-reference).
3. Run `npx typewriter init`. This command enables you to use the Typewriter quickstart wizard that generates a [`typewriter.yml`](#configuration-reference) configuration, along with your first Typewriter client. The command creates a `typewriter.yml` file in your repository. For more information on the format of this file, see the [Typewriter Configuration Reference](#configuration-reference).

Typewriter creates the class file with the package name `typewriter`. Segment recommends you to enter the right package name during `npx typewriter init` by choosing to review the Advanced Options for Kotlin. You can also enter the right package name directly in `typewriter.yml`:

Expand All @@ -234,19 +234,21 @@ To get started using Typewriter with Kotlin:
sdk: kotlin
languageOptions:
package: com.segment.typewriter
```
```

> info ""
> Run `npx typewriter` to regenerate your Typewriter client. You need to do this each time you update your Tracking Plan.

You can now use your Typewriter client in your Android Kotlin or Java application as extensions to any `Analytics` object:

Kotlin:

```kotlin
// Import your auto-generated Typewriter client:
import com.segment.generated.*
analytics.orderCompleted(OrderCompleted(orderID = "110", total = 39.98))
```

Java:
```java
// Import your auto-generated Typewriter client:
Expand All @@ -261,7 +263,7 @@ TypewriterAnalytics.with(this).orderCompleted(
);
```

## React Native Quickstart
## React Native quickstart

To get started with React Native:
1. Follow the [Getting Started guide for React Native](/docs/connections/sources/catalog/libraries/mobile/react-native/).
Expand All @@ -273,7 +275,7 @@ To get started with React Native:

3. Run `npx typewriter init` to use the Typewriter quickstart wizard that generates a `typewriter.yml` configuration along with your first Typewriter client.

This command creates a `typewriter.yml` file in your repo. For more information on the format of this file, see the [Typewriter Configuration Reference](#configuration-reference). The command also adds a new Typewriter / Segment client in `./analytics` (or whichever path you configured). You can use this interchangeably as a normal React Native Segment client. It contains additional methods for your tracking plan:
This command creates a `typewriter.yml` file in your repository. For more information on the format of this file, see the [Typewriter Configuration Reference](#configuration-reference). The command also adds a new Typewriter/Segment client in `./analytics` (or whichever path you configured). You can use this interchangeably as a normal React Native Segment client. It contains additional methods for your tracking plan:

```ts
import {
Expand Down Expand Up @@ -318,10 +320,11 @@ To get started with React Native:
// Remember this is just an extended client with the typewriter methods so all the normal segment methods still work!
segmentClient.track('Untyped event');
```

> info ""
> Run `npx typewriter` to regenerate your Typewriter client. You need to do this each time you update your Tracking Plan.

## Adding Events
## Adding events

To update or add a new event to a Typewriter client, first apply your changes to your Tracking Plan. Then run the following:

Expand All @@ -330,20 +333,20 @@ To update or add a new event to a Typewriter client, first apply your changes to
$ npx typewriter
```

## API Token Configuration
## API token configuration

Typewriter requires a Segment API token to fetch Tracking Plans from the [Segment Public API](https://docs.segmentapis.com/){:target="_blank”}.


You must be a workspace owner to create Segment API tokens.
You must have the [Workspace Owner role](/docs/segment-app/iam/roles/) to create Segment API tokens.

To create an API token:
1. Click on the **Tokens** tab on the [Access Management](https://app.segment.com/goto-my-workspace/settings/access-management){:target="_blank”} page and click **Create Token**.
2. Choose Segment's Public API.
3. Add a description for the token and assign access. If you choose *Workspace Member*, you only need to select **Tracking Plan Read-Only** for the Resource Role, as Typewriter only needs the *Tracking Plan Read-Only* role.
4. Click **Create**.

Typewriter looks for an API token in three ways, in the following order:
Typewriter looks for an API token in the following order:
1. If a token is piped through, it will use that token. For example, `echo $TW_TOKEN | typewriter build`.
2. Typewriter executes a token script from the `typewriter.yml`. See [Token Script](#token-script) for more information.
3. Typewriter reads the contents of the `~/.typewriter` file.
Expand Down Expand Up @@ -401,7 +404,7 @@ If this isn't possible you can also check in the full generated client. Segment,

## Configuration Reference

Typewriter stores its configuration in a `typewriter.yml` file in the root of your repo. A sample configuration might look like this:
Typewriter stores its configuration in a `typewriter.yml` file in the root of your repository. A sample configuration might look like this:

```yml
# Segment Typewriter Configuration Reference (https://github.com/segmentio/typewriter)
Expand Down Expand Up @@ -566,7 +569,7 @@ typewriter.setTypewriterOptions({

## Known Limitations

Typewriter only supports `track` calls. However, you can continue to use the underlying (untyped) analytics instance to perform `identify`, `group`, `page`, `screen`, and `alias` calls.
Typewriter only supports Track calls. However, you can continue to use the underlying (untyped) analytics instance to perform Identify, Group, Page, Screen, and Alias calls.

Not all languages support run-time validation. Currently, `analytics.js` and `analytics-node` support it using [AJV](https://github.com/epoberezkin/ajv){:target="_blank"} (both for JavaScript and TypeScript projects) while `analytics-swift` and `analytics-kotlin` don't support run-time validation. Typewriter also does not support event validation using the Common JSON Schema.

Expand All @@ -576,4 +579,4 @@ If you're interested in contributing, [open an issue on GitHub](https://github.c

## Feedback

Segment welcomes feedback you may have on your experience with Typewriter. To contact Segment, [open an issue on GitHub](https://github.com/segmentio/typewriter/issues/new){:target="_blank”}.
Segment welcomes feedback you may have on your experience with Typewriter. To contact us, [open an issue on GitHub](https://github.com/segmentio/typewriter/issues/new){:target="_blank”}.
Loading