# Send user events

The SDK enables you to monitor and record user behaviors as events. In this guide, you'll learn to:&#x20;

* Send both custom and predefined events
* Build events
* Add your own dimensions to events.

### Send User Events

Publishing an event requires requires you to create an event object which you then can pass to `publish(event:)`:

```swift
let event = UserEvent("namespace_module_action").build()
sdk.publish(event: event)
```

By calling `build()` on a `UserEvent` instance you are creating an immutable `PublishableUserEvent` object which you can pass to `publish(event:)` as often as you need. Calling `build()` does not modify the `UserEvent` object if you need to modify it again.

The SDK defines a broad range of event names with defined semantics for you to make use of. For each event the SDK also documents which values should be supplied as a dimension. For example, to track the navigation from your menu screen to a game screen, you could record the following event:

```swift
sdk.publish(event: UserScreenShowEvent(elementName: "Game Main", elementId: "SCREEN_GAME_MAIN").build())
```

### Building a user event

A `UserEvent` instance is actually a builder for the event we later send to the backend. You can either provide all parameters via the constructor if you want or you can initialize an empty event and later call setters for the different properties. The only thing you need to create a new event is the name of the event, which may also not be empty (and can later no longer be changed). The following constructors are provided:

```swift
public class UserEvent {
    public init(name: EventDetails)
    public init(name: EventDetails, value: Double, unit: Unit)
    public init(name: EventDetails, money: Money)
    public init(name: EventDetails, dimension1: String)
    public init(name: EventDetails, dimension1: String, dimension2: String)
    public init(name: EventDetails, dimension1: String, dimension2: String, dimension3: String)
    public init(name: EventDetails, dimension1: String, dimension2: String, dimension3: String, value: Double, unit: Unit)
    public init(name: EventDetails, dimension1: String, dimension2: String, dimension3: String, money: Money)
}
```

The `EventDetails` class captures the name of a user event with some additional details. Those are the `category`, `element`, and `action` of the event and can be used to group events together. For example, all events generated by the SDK regarding the session tracking share the category `session`.

`value` and `unit` can only be provided together and default to `1` and `.count`. Alternatively, an event can carry a monetary value instead of a value with a unit. The three dimensions default to the empty string if not specified. You can also set the properties after initialization:

```swift
public protocol UserEventBuilder {
    func with(dimension1: String) -> UserEventBuilder
    func with(dimension2: String) -> UserEventBuilder
    func with(dimension3: String) -> UserEventBuilder
    func with(value: Double, unit: Unit) -> UserEventBuilder
    func with(money: Money) -> UserEventBuilder

    func with(count: Double) -> UserEventBuilder
    func with(seconds: Double) -> UserEventBuilder
    func with(milliseconds: Double) -> UserEventBuilder

    func build() -> PublishableUserEvent
}
```

`with(count:)`, `with(seconds:)`, and `with(milliseconds:)` are provided for your convenience if you know an event will always use a specific unit.

### Sending a user event to the backend

If you are interested in whether an event could be successfully send to the backend, you can await the future returned by `publish(event:)`:

```swift
sdk.publish(event: event).observe(using: { result in
    switch result {
    case .failure(let error):
        // event failed to reach our servers
    case .success(_):
        // the event was successfully published
    }
})
```

### User event restrictions

The following restrictions apply to user events:

* The name must not be empty.
* Name, action, category, and element must be shorter than 256 characters and can only consist of printable ISO 8859-1 characters (U+0020 to U+007E as well as U+00A0 to U+00FF).
* Dimension values must be shorter than 4096 characters and can only consist of printable ISO 8859-1 characters (U+0020 to U+007E as well as U+00A0 to U+00FF).
* The value of a user event must be finite (i.e., not NaN or ±Infinity).
* If you provide a monetary value, the currency needs to be a 3 letter uppercase ISO 4217 string.
