Custom events

  • Latest Dynatrace
  • How-to guide
  • Published Dec 22, 2025

Dynatrace allows you to send custom events to track user interactions, business metrics, and application-specific data. You can also enrich all events with additional context using event modifiers.

Send custom events

Use sendEvent() to report custom events with optional duration and event properties.

Basic usage

// Simple event
Dynatrace.sendEvent(DTXEventData())
// Event with duration (in milliseconds)
Dynatrace.sendEvent(DTXEventData().withDuration(150))

Add event properties

Add custom properties to provide context for your events. Property keys must be prefixed with event_properties..

Dynatrace.sendEvent(DTXEventData()
.withDuration(250)
.addEventProperty("event_properties.checkout_step", value: "payment_confirmed")
.addEventProperty("event_properties.cart_value", value: 149.99)
.addEventProperty("event_properties.item_count", value: 3))

Property naming rules

  • Keys must be prefixed with event_properties..
  • Field names must contain only alphanumeric characters, underscores, and dots.
  • Each dot must be followed by an alphabetic character.
  • Each underscore must be followed by an alphabetic character or number.
  • Values must be primitive types (String, Int, Double, Bool).

Valid examples:

  • event_properties.checkout_step
  • event_properties.cart.total_value
  • event_properties.user_tier

Event modifiers

Event modifiers allow you to intercept and modify all events before they are sent to Dynatrace. Use them to add common properties, redact sensitive information, or filter events.

Add an event modifier

let subscriber = Dynatrace.addEventModifier { event in
// Add experiment tracking to all events
event.fields["event_properties.experiment_id"] = "checkout_flow_v2"
event.fields["event_properties.variant"] = "treatment_a"
return event
}

Filter events

Return nil to discard an event:

let subscriber = Dynatrace.addEventModifier { event in
// Filter out events from test users
if event.fields["event_properties.is_test_user"] as? Bool == true {
return nil // Discard this event
}
return event
}

Redact sensitive data

let subscriber = Dynatrace.addEventModifier { event in
// Redact user IDs from URLs
if let url = event.fields["url.full"] as? String {
let redactedUrl = url.replacingOccurrences(
of: #"/users/\w+/"#,
with: "/users/{id}/",
options: .regularExpression
)
event.fields["url.full"] = redactedUrl
}
return event
}

Remove event modifiers

// Store the subscriber when adding the modifier
let subscriber = Dynatrace.addEventModifier { event in
event.fields["event_properties.custom"] = "value"
return event
}
// Remove when no longer needed
Dynatrace.removeEventModifier(subscriber)

Modifier limitations

Event modifiers have restrictions on which fields can be modified to ensure data integrity.

Modifiable fields

The following fields can be modified or added:

  • event_properties.*—custom event properties
  • url.full—the complete request URL
  • exception.stack_trace—exception stack traces

Read-only fields

Most standard Dynatrace fields cannot be modified, including:

  • duration
  • start_time
  • http.request.method
  • http.response.status_code
  • span.id
  • trace.id
  • All system-generated metadata

Attempting to modify read-only fields will have no effect. The original values will be preserved.

Additional rules

  • Reserved namespaces—fields prefixed with dt. or characteristics. cannot be added or modified.

Modifier examples

Add user context to all events

class UserContext {
static var userId: String?
static var userTier: String?
}
func setupEventEnrichment() {
_ = Dynatrace.addEventModifier { event in
if let userId = UserContext.userId {
event.fields["event_properties.user_id_hash"] = userId.hashValue
}
if let userTier = UserContext.userTier {
event.fields["event_properties.user_tier"] = userTier
}
return event
}
}

Add feature flags

func setupFeatureFlagTracking(featureFlags: [String: Bool]) {
_ = Dynatrace.addEventModifier { event in
for (key, value) in featureFlags {
event.fields["event_properties.ff_\(key)"] = value
}
return event
}
}

Conditional event enrichment

func setupConditionalEnrichment() {
_ = Dynatrace.addEventModifier { event in
// Only enrich HTTP events
if event.fields["http.request.method"] != nil {
event.fields["event_properties.api_client"] = "ios_app"
event.fields["event_properties.api_version"] = "v2"
}
// Only enrich error events
if event.fields["exception.type"] != nil {
event.fields["event_properties.error_context"] = "user_session"
}
return event
}
}

Important considerations

  • Execution order—modifiers run in the order they were added.
  • Returning nil—discards the event; subsequent modifiers won't run.
  • Performance—keep modifiers efficient—they run for every event.
  • Primitive values—event properties can only contain primitive types (String, Int, Double, Bool).
  • Error handling—eceptions in modifiers are logged but don't block other modifiers.
  • Thread safety—modifiers may be called from any thread. Ensure your code is thread-safe.
Related tags
Digital Experience