# Track events with the .NET tracker
> Track page views, structured events, screen views, and custom self-describing events with the .NET tracker SDK.
> Source: https://docs.snowplow.io/docs/sources/net-tracker/event-tracking/
> Documentation index: https://docs.snowplow.io/llms.txt

Events supported by the .NET Tracker at a glance:

| **Events**                    | **Description**                                        |
| ----------------------------- | ------------------------------------------------------ |
| `Track(PageView)`             | Track and record views of web pages                    |
| `Track(ScreenView)`           | Track the user viewing a screen within the application |
| `Track(Structured)`           | Track a Snowplow custom structured event               |
| `Track(Timing)`               | Track a Timing with Category event                     |
| `Track(Unstructured)`         | Track a Snowplow custom unstructured event             |
| `Track(EcommerceTransaction)` | Track an ecommerce transaction and its items           |

### Track page views with `Track(PageView)`

You can use `Track(PageView)` to track a user viewing a web page within your app.

Arguments are:

| **Argument**     | **Description**                      | **Required?** | **Type**         |
| ---------------- | ------------------------------------ | ------------- | ---------------- |
| `pageUrl`        | The URL of the page                  | Yes           | `string`         |
| `pageTitle`      | The title of the page                | No            | `string`         |
| `referrer`       | The address which linked to the page | No            | `string`         |
| `customContexts` | Optional custom context              | No            | `List<IContext>` |
| `trueTimestamp`  | Optional true-timestamp              | No            | `long`           |
| `eventId`        | Optional custom event id             | No            | `string`         |

Examples:

```csharp
t1.Track(new PageView()
    .SetPageUrl("www.example.com")
    .SetPageTitle("example")
    .SetReferrer("www.referrer.com")
    .Build());

t1.Track(new PageView()
    .SetPageUrl("www.example.com")
    .SetPageTitle("example")
    .SetReferrer("www.referrer.com")
    .SetCustomContext(contextList)
    .SetTrueTimestamp(1423583655000)
    .SetEventId("uid-1")
    .Build());
```

### Track screen views with `Track(ScreenView)`

Use `Track(ScreenView)` to track a user viewing a screen (or equivalent) within your app. You **must** use either `name` or `id`. Arguments are:

| **Argument**             | **Description**                     | **Required?** | **Type**         |
| ------------------------ | ----------------------------------- | ------------- | ---------------- |
| `name`                   | Human-readable name for this screen | No            | `string`         |
| `id`                     | Unique identifier for this screen   | No            | `string`         |
| `customContexts`         | Optional custom context             | No            | `List<IContext>` |
| `deviceCreatedTimestamp` | Optional device-created-timestamp   | No            | `long`           |
| `trueTimestamp`          | Optional true-timestamp             | No            | `long`           |
| `eventId`                | Optional custom event id            | No            | `string`         |

Examples:

```csharp
t1.Track(new ScreenView()
    .SetName("HUD > Save Game")
    .SetId("screen23")
    .Build());

t1.Track(new ScreenView()
    .SetName("HUD > Save Game")
    .SetId("screen23")
    .SetCustomContext(contextList)
    .SetTrueTimestamp(1423583655000)
    .SetEventId("uid-1")
    .Build());
```

### Track structured events with `Track(Structured)`

Use `Track(Structured)` to track a custom event happening in your app which fits the Google Analytics-style structure of having up to five fields (with only the first two required):

| **Argument**             | **Description**                                                  | **Required?** | **Type**         |
| ------------------------ | ---------------------------------------------------------------- | ------------- | ---------------- |
| `category`               | The grouping of structured events which this `action` belongs to | Yes           | `string`         |
| `action`                 | Defines the type of user interaction which this event involves   | Yes           | `string`         |
| `label`                  | A string to provide additional dimensions to the event data      | No            | `string`         |
| `property`               | A string describing the object or the action performed on it     | No            | `string`         |
| `value`                  | A value to provide numerical data about the event                | No            | `double`         |
| `customContexts`         | Optional custom context                                          | No            | `List<IContext>` |
| `deviceCreatedTimestamp` | Optional device-created-timestamp                                | No            | `long`           |
| `trueTimestamp`          | Optional true-timestamp                                          | No            | `long`           |
| `eventId`                | Optional custom event id                                         | No            | `string`         |

Examples:

```csharp
t1.Track(new Structured()
    .SetCategory("shop")
    .SetAction("add-to-basket")
    .Build());

t1.Track(new Structured()
    .SetCategory("shop")
    .SetAction("add-to-basket")
    .SetLabel("Add To Basket")
    .SetProperty("pcs")
    .SetValue(2.00)
    .SetCustomContext(contextList)
    .SetTrueTimestamp(1423583655000)
    .SetEventId("uid-1")
    .Build());
```

### Track timing events with `Track(Timing)`

Use `Track(Timing)` to track an event related to a custom timing.

| **Argument**             | **Description**                        | **Required?** | **Type**         |
| ------------------------ | -------------------------------------- | ------------- | ---------------- |
| `category`               | The category of the timed event        | Yes           | `string`         |
| `label`                  | The label of the timed event           | No            | `string`         |
| `timing`                 | The timing measurement in milliseconds | Yes           | `int`            |
| `variable`               | The name of the timed event            | Yes           | `string`         |
| `customContexts`         | Optional custom context                | No            | `List<IContext>` |
| `deviceCreatedTimestamp` | Optional device-created-timestamp      | No            | `long`           |
| `trueTimestamp`          | Optional true-timestamp                | No            | `long`           |
| `eventId`                | Optional custom event id               | No            | `string`         |

Examples:

```csharp
t1.Track(new Timing()
    .SetCategory("category")
    .SetVariable("variable")
    .SetTiming(1)
    .Build());

t1.Track(new Timing()
    .SetCategory("category")
    .SetVariable("variable")
    .SetTiming(1)
    .SetLabel("label")
    .SetCustomContext(contextList)
    .SetTrueTimestamp(1423583655000)
    .SetEventId("uid-1")
    .Build());
```

#### Track unstructured events with `Track(SelfDescribing)`

Custom unstructured events are a flexible tool that enable Snowplow users to define their own event types and send them into Snowplow.

When a user sends in a custom unstructured event, they do so as a JSON of name-value properties, that conforms to a JSON schema defined for the event earlier.

Use `Track(SelfDescribing)` to track a custom event which consists of a name and an unstructured set of properties. This is useful when:

- You want to track event types which are proprietary/specific to your business (i.e. not already part of Snowplow), or
- You want to track events which have unpredictable or frequently changing properties

The arguments are as follows:

| **Argument**             | **Description**                   | **Required?** | **Type**             |
| ------------------------ | --------------------------------- | ------------- | -------------------- |
| `eventData`              | The properties of the event       | Yes           | `SelfDescribingJson` |
| `customContexts`         | Optional custom context           | No            | `List<IContext>`     |
| `deviceCreatedTimestamp` | Optional device-created-timestamp | No            | `long`               |
| `trueTimestamp`          | Optional true-timestamp           | No            | `long`               |
| `eventId`                | Optional custom event id          | No            | `string`             |

Example event json to track:

```csharp
{
  "schema": "iglu:com.acme/save_game/jsonschema/1-0-0",
  "data": {
    "levelName": "Barrels o' Fun",
    "levelIndex": 23
  }
}
```

How to set it up?

```csharp
// Create a Dictionary of your event data
Dictionary<string, object> eventDict = new Dictionary<string, object>();
eventDict.Add("levelName", "Barrels o' Fun");
eventDict.Add("levelIndex", 23);

// Create your event data
SelfDescribingJson eventData = new SelfDescribingJson("iglu:com.acme/save_game/jsonschema/1-0-0", eventDict);

// Track your event with your custom event data
t1.Track(new SelfDescribing()
    .SetEventData(eventData)
    .Build());

// OR

t1.Track(new SelfDescribing()
    .SetEventData(eventData)
    .SetCustomContext(contextList)
    .SetTrueTimestamp(1423583655000)
    .SetEventId("uid-1")
    .Build());
```

For more on JSON schema, see the [blog post](https://snowplowanalytics.com/blog/2014/05/15/introducing-self-describing-jsons/).

### Track ecommerce transactions with `Track(EcommerceTransaction)`

Use `Track(EcommerceTransaction)` to track an ecommerce transaction.

Arguments:

| **Argument**             | **Description**                   | **Required?** | **Type**                         |
| ------------------------ | --------------------------------- | ------------- | -------------------------------- |
| `orderId`                | ID of the eCommerce transaction   | Yes           | `string`                         |
| `totalValue`             | Total transaction value           | Yes           | `double`                         |
| `affiliation`            | Transaction affiliation           | No            | `string`                         |
| `taxValue`               | Transaction tax value             | No            | `double`                         |
| `shipping`               | Delivery cost charged             | No            | `double`                         |
| `city`                   | Delivery address city             | No            | `string`                         |
| `state`                  | Delivery address state            | No            | `string`                         |
| `country`                | Delivery address country          | No            | `string`                         |
| `currency`               | Transaction currency              | No            | `string`                         |
| `items`                  | Items in the transaction          | Yes           | `List<EcommerceTransactionItem>` |
| `customContexts`         | Optional custom context           | No            | `List<IContext>`                 |
| `deviceCreatedTimestamp` | Optional device-created-timestamp | No            | `long`                           |
| `trueTimestamp`          | Optional true-timestamp           | No            | `long`                           |
| `eventId`                | Optional custom event id          | No            | `string`                         |

The `items` argument is a `List` of individual `EcommerceTransactionItem` elements representing the items in the ecommerce transaction. Note that `Track(EcommerceTransaction)` fires multiple events: one transaction event for the transaction as a whole, and one transaction item event for each element of the `items` `List`.

Each transaction item event will have the same device created timestamp, true timestamp, orderId, and currency as the main transaction event.

#### `EcommerceTransactionItem`

#### Using Snowplow\.Tracker (.NET Standard) or Snowplow\.Tracker.PlatformExtensions (PCL)

To instantiate a `EcommerceTransactionItem` in your code, simply use the following constructor signature:

```csharp
EcommerceTransactionItem item = new EcommerceTransactionItem ()
      .SetSku ("sku")
      .SetPrice (10.2)
      .SetQuantity (1)
      .SetName ("name")
      .SetCategory ("category")
      .Build ()
```

These are the fields that can appear as elements in each `EcommerceTransactionItem` element of the transaction item's `List`:

| **Field**        | **Description**          | **Required?** | **Type**         |
| ---------------- | ------------------------ | ------------- | ---------------- |
| `sku`            | Item SKU                 | Yes           | `string`         |
| `price`          | Item price               | Yes           | `double`         |
| `quantity`       | Item quantity            | Yes           | `int`            |
| `name`           | Item name                | No            | `string`         |
| `category`       | Item category            | No            | `string`         |
| `customContexts` | Optional custom context  | No            | `List<IContext>` |
| `eventId`        | Optional custom event id | No            | `string`         |

Example of tracking a transaction containing two items:

```csharp
// Create some Transaction Items
EcommerceTransactionItem item1 = new EcommerceTransactionItem ()
    .SetSku ("item_sku_1")
    .SetPrice (10.2)
    .SetQuantity (1)
    .SetName ("item_name_1")
    .SetCategory ("item_category")
    .Build ();

EcommerceTransactionItem item2 = new EcommerceTransactionItem()
    .SetSku("item_sku_2")
    .SetPrice(1.00)
    .SetQuantity(1)
    .SetName("item_name_2")
    .SetCategory("item_category")
    .Build();

// Add these items to a List
List<EcommerceTransactionItem> items = new List<EcommerceTransactionItem>();
items.Add(item1);
items.Add(item2);

// Now Track the Transaction by using this list of items as an argument
tracker.Track(new EcommerceTransaction()
    .SetOrderId("order_id_1")
    .SetTotalValue(300.00)
    .SetAffiliation("my_affiliate")
    .SetTaxValue(30.00)
    .SetShipping(10.00)
    .SetCity("Boston")
    .SetState("Massachusetts")
    .SetCountry("USA")
    .SetCurrency("USD")
    .SetItems(items)
    .Build());
```

### Custom Contexts

Custom contexts are Self Describing Jsons with extra descriptive information that can be optionally attached to any Snowplow event with `SetCustomContexts(...)`. We provide several builders for Snowplow custom contexts as well as a generic builder if you wish to define and send your own custom contexts!

For ease of development you are also able to extend the `IContext` interface or the `AbstractContext` class for your own contexts if you so wish.

All of these contexts will need to be combined into a `List<IContext>` before being attachable to Snowplow Events.

#### `DesktopContext`

The following arguments can be used in a DesktopContext:

| **Field**            | **Description**                     | **Required?** | **Type** |
| -------------------- | ----------------------------------- | ------------- | -------- |
| `osType`             | The Operating System Type           | Yes           | `string` |
| `osVersion`          | The Version of the Operating System | Yes           | `string` |
| `osServicePack`      | Service Pack information            | No            | `string` |
| `osIs64Bit`          | If the OS is 32 or 64 bit           | No            | `bool`   |
| `deviceManufacturer` | Who made the device                 | No            | `string` |
| `deviceModel`        | What is the device model            | No            | `string` |
| `processorCount`     | How many cores does the device have | No            | `int`    |

An example of a DesktopContext construction:

```csharp
DesktopContext context = new DesktopContext ()
    .SetOsType("OS-X")
    .SetOsVersion("10.10.5")
    .SetOsServicePack("Yosemite")
    .SetOsIs64Bit(true)
    .SetDeviceManufacturer("Apple")
    .SetDeviceModel("Macbook Pro")
    .SetDeviceProcessorCount(4)
    .Build ();
```

#### `MobileContext`

The following arguments can be used in a MobileContext:

| **Field**            | **Description**                     | **Required?** | **Type**      |
| -------------------- | ----------------------------------- | ------------- | ------------- |
| `osType`             | The Operating System Type           | Yes           | `string`      |
| `osVersion`          | The Version of the Operating System | Yes           | `string`      |
| `deviceManufacturer` | Who made the device                 | Yes           | `string`      |
| `deviceModel`        | What is the device model            | Yes           | `string`      |
| `carrier`            | The name of the carrier             | No            | `string`      |
| `networkType`        | The type of network                 | No            | `NetworkType` |
| `networkTechnology`  | The networks technlogy              | No            | `string`      |
| `openIdfa`           | An OpenIDFA UUID                    | No            | `string`      |
| `appleIdfa`          | An Apple IDFA UUID                  | No            | `string`      |
| `appleIdfv`          | An Apple IDFV UUID                  | No            | `string`      |
| `androidIdfa`        | An Android IDFA UUID                | No            | `string`      |

An example of a MobileContext construction:

#### `GeoLocationContext`

The following arguments can be used in a GeoLocationContext:

| **Field**                   | **Description**            | **Required?** | **Type** |
| --------------------------- | -------------------------- | ------------- | -------- |
| `latitude`                  | The user latitude          | Yes           | `double` |
| `longitude`                 | The user longitude         | Yes           | `double` |
| `latitudeLongitudeAccuracy` | The user lat-long accuracy | No            | `double` |
| `altitude`                  | The user altitude          | No            | `double` |
| `altitudeAccuracy`          | The user alt accuracy      | No            | `double` |
| `bearing`                   | The user bearing           | No            | `double` |
| `speed`                     | The user speed             | No            | `double` |
| `timestamp`                 | A timestamp in ms          | No            | `long`   |

An example of a GeoLocationContext construction:

```csharp
GeoLocationContext context = new GeoLocationContext ()
    .SetLatitude(123.564)
    .SetLongitude(-12.6)
    .SetLatitudeLongitudeAccuracy(5.6)
    .SetAltitude(5.5)
    .SetAltitudeAccuracy(2.1)
    .SetBearing(3.2)
    .SetSpeed(100.2)
    .SetTimestamp(1234567890000)
    .Build ();
```

#### `GenericContext`

The GenericContext is a simple builder with three functions:

- `SetSchema(string)` : Sets the Context Schema Path
- `Add(string, object)` : Adds a single key-pair value to the data packet of this context
- `AddDict(string, object)` : Adds a dictionary of key-pair values to the data packet

You must set a schema string or a RuntimeException will be thrown.

An example of a GenericContext construction:

```csharp
GenericContext context = new GenericContext()
    .SetSchema("iglu:com.acme/acme_context/jsonschema/1-0-0")
    .Add("context", "custom")
    .Build();
```

### SelfDescribingJson

A `SelfDescribingJson` is used as a wrapper around a `Dictionary<string, object>`. After creating the Dictionary you want to wrap you can create a `SelfDescribingJson` using the following:

```csharp
// Data as a Dictionary
Dictionary<string, object> data = new Dictionary<string, object>();
data.Add("Event", "Data")

// We then create a new SelfDescribingJson
SelfDescribingJson json = new SelfDescribingJson("iglu:com.acme/example/jsonschema/1-0-0", data);
```

This object is now ready to be Tracked within an SelfDescribing Event.

You can create a SelfDescribingJson with the following arguments:

| **Argument** | **Description**                           | **Required?** | **Type**                    |
| ------------ | ----------------------------------------- | ------------- | --------------------------- |
| `schema`     | JsonSchema that describes the data        | Yes           | `string`                    |
| `data`       | Data that will be validated by the schema | No            | `Dictionary<string,object`> |
