Skip to content

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# TypeDescription
stringText values
intInteger values
doubleDecimal values (float is not supported)
boolTrue/false values
DateTimeTimestamp values

Visibility

Event classes must be declared public so the build processor can discover and scan them during schema generation.