Defining Custom Events
Analytics events are plain C# classes decorated with attributes. The SDK’s build processor scans your assemblies, reads the attributes, and generates the event schema automatically.
Minimal event
using TactileModules.TactileAnalyticsModule;
[TactileAnalytics.EventAttribute("levelCompleted")]public class LevelCompleteEvent{ [EventPropertyDescription("The level identifier.")] private TactileAnalytics.RequiredParam<string> levelName { get; set; }
public LevelCompleteEvent(string levelName) { this.levelName = levelName; }}Full example with multiple properties
using TactileModules.TactileAnalyticsModule;
[TactileAnalytics.EventAttribute("levelCompleted")][EventCategory("Progression")][EventDescription("Fired when the player successfully finishes a level.")]public class LevelCompleteEvent{ [EventPropertyDescription("The level identifier, e.g. 'world1_level3'.")] private TactileAnalytics.RequiredParam<string> levelName { get; set; }
[EventPropertyDescription("Stars earned on completion (0–3).")] private TactileAnalytics.RequiredParam<int> starsEarned { get; set; }
[EventPropertyDescription("Elapsed time in seconds.")] private TactileAnalytics.OptionalParam<double> elapsedSeconds { get; set; }
[EventPropertyDescription("Whether any boosters were active during this attempt.")] private TactileAnalytics.RequiredParam<bool> boostersActive { get; set; }
public LevelCompleteEvent(string levelName, int starsEarned, bool boostersActive, double elapsedSeconds = 0) { this.levelName = levelName; this.starsEarned = starsEarned; this.boostersActive = boostersActive; this.elapsedSeconds = elapsedSeconds; }}Attribute reference
[TactileAnalytics.EventAttribute(string name)]
Required on the class. name is the event name that appears in the data warehouse. Use snake_case.
[EventCategory(string category)]
Optional. Groups events in the dashboard UI. Examples: "Progression", "Monetisation", "Debug".
[EventDescription(string description)]
Optional but strongly recommended. Human-readable description of when this event fires. Shown in the schema viewer and used for generated documentation.
[EventPropertyDescription(string description)]
Required on each property you want included in the schema. Without this attribute, the property is ignored by the schema generator.
[EventChangeReason(string reason, string developer, string stakeholder)]
Required when modifying an existing event schema. Tracks why the schema changed, who made the change, and who requested it. All three parameters are required.
[EventChangeReason("Add elapsed time property", "dev@studio.com", "pm@studio.com")][PersonalData]
Marks a property as containing personal or sensitive data. Used for data governance and compliance.
[PersonalData][EventPropertyDescription("Player email if provided.")]private TactileAnalytics.OptionalParam<string> email { get; set; }Required and optional properties
Properties are wrapped in generic structs to indicate whether they are required or optional:
RequiredParam<T>
The schema generator marks these properties as required. The value must always be provided.
[EventPropertyDescription("The level identifier.")]private TactileAnalytics.RequiredParam<string> levelName { get; set; }OptionalParam<T>
The schema generator marks these properties as optional. Use for values that may not always be available.
[EventPropertyDescription("Local client price from the store.")]private TactileAnalytics.OptionalParam<double> localPrice { get; set; }Both types have implicit conversion operators, so you can assign values directly:
this.levelName = "world1_level3";this.localPrice = 4.99;Supported types for T
| C# Type | Description |
|---|---|
string | Text values |
int | Integer values |
double | Decimal values (float is not supported) |
bool | True/false values |
DateTime | Timestamp values |
Visibility
Event classes must be declared public so the build processor can discover and scan them during schema generation.