Events edits

This commit is contained in:
Savya Bikram Shah
2026-07-06 14:17:50 +05:45
parent 3df3d923fb
commit e0a7fa9735
6 changed files with 42 additions and 17 deletions

View File

@@ -11,9 +11,9 @@ namespace Darkmatter.Core.Contracts.Services.Analytics
// Onboarding / activation funnel // Onboarding / activation funnel
public const string IntroStarted = "intro_started"; public const string IntroStarted = "intro_started";
public const string IntroCompleted = "intro_completed"; public const string IntroCompleted = "intro_completed";
public const string TutorialStarted = "tutorial_started"; public const string TutorialStarted = "tutorial_begin";
public const string TutorialStepCompleted = "tutorial_step_completed"; public const string TutorialStepCompleted = "tutorial_step_completed";
public const string TutorialCompleted = "tutorial_completed"; public const string TutorialCompleted = "tutorial_complete";
public const string PlayClicked = "play_clicked"; public const string PlayClicked = "play_clicked";
public const string FirstDrawingStarted = "first_drawing_started"; public const string FirstDrawingStarted = "first_drawing_started";
@@ -32,10 +32,9 @@ namespace Darkmatter.Core.Contracts.Services.Analytics
public const string ShapeAssembled = "shape_assembled"; public const string ShapeAssembled = "shape_assembled";
public const string ColorApplied = "color_applied"; public const string ColorApplied = "color_applied";
// Progression & content. level_start is a GA4-recommended games event; level_complete is our // Progression & content. level_start and level_end are GA4-recommended games events.
// custom completion marker (GA4's own pair would be level_end + success).
public const string LevelStart = "level_start"; public const string LevelStart = "level_start";
public const string LevelComplete = "level_complete"; public const string LevelComplete = "level_end";
public const string AllContentCompleted = "all_content_completed"; public const string AllContentCompleted = "all_content_completed";
// Gallery capture (pre-existing) // Gallery capture (pre-existing)

View File

@@ -4,14 +4,14 @@ namespace Darkmatter.Core.Contracts.Services.Analytics
/// Canonical analytics parameter keys. Pass a consistent set on every gameplay event so reports can /// Canonical analytics parameter keys. Pass a consistent set on every gameplay event so reports can
/// answer "which drawing did people quit on", not just "how many quit". Each key used in reports must /// answer "which drawing did people quit on", not just "how many quit". Each key used in reports must
/// be registered as a Custom Dimension in the Firebase console. GA4 limit: 25 params per event. /// be registered as a Custom Dimension in the Firebase console. GA4 limit: 25 params per event.
/// GA4-recommended events (level_start/level_complete/ad_impression) reuse GA4's reserved param names /// GA4-recommended events (level_start/level_end/ad_impression) reuse GA4's reserved param names
/// (level_name, success, value, currency, ad_platform, ad_format, ad_unit_name) so they're recognised. /// (level_name, success, value, currency, ad_platform, ad_format, ad_unit_name) so they're recognised.
/// </summary> /// </summary>
public static class AnalyticsParams public static class AnalyticsParams
{ {
// Content identity // Content identity
public const string DrawingId = "drawing_id"; public const string DrawingId = "drawing_id";
public const string LevelName = "level_name"; // GA4 reserved (level_start/level_complete) public const string LevelName = "level_name"; // GA4 reserved (level_start/level_end)
// Tutorial // Tutorial
public const string StepId = "step_id"; public const string StepId = "step_id";
@@ -23,7 +23,7 @@ namespace Darkmatter.Core.Contracts.Services.Analytics
public const string Attempts = "attempts"; public const string Attempts = "attempts";
public const string ApplyIndex = "apply_index"; public const string ApplyIndex = "apply_index";
public const string CompletionCount = "completion_count"; public const string CompletionCount = "completion_count";
public const string Success = "success"; // GA4 reserved (level_complete) public const string Success = "success"; // GA4 reserved (level_end)
// Monetization (GA4 ad_impression reserved names) // Monetization (GA4 ad_impression reserved names)
public const string Value = "value"; public const string Value = "value";

View File

@@ -39,6 +39,11 @@ namespace Darkmatter.Services.Ads
[SerializeField, Min(0)] [SerializeField, Min(0)]
private int maxInterstitialsPerSession = 8; private int maxInterstitialsPerSession = 8;
[Tooltip(
"Enable only after verifying Firebase/AdMob is not already auto-logging ad_impression for the same ads. Leaving this off avoids duplicate ad_impression counts in GA4/Firebase.")]
[SerializeField]
private bool logManualAdImpressionEvents;
public bool IsInitialized => _initialized; public bool IsInitialized => _initialized;
public event Action<AdFormat, AdLoadState> LoadStateChanged; public event Action<AdFormat, AdLoadState> LoadStateChanged;
@@ -653,11 +658,12 @@ namespace Darkmatter.Services.Ads
ad.OnAdClicked += () => LogAdClicked(format); ad.OnAdClicked += () => LogAdClicked(format);
} }
// Ad revenue: GA4-recommended ad_impression carries value+currency from AdMob's paid callback — // AdMob/Firebase can auto-log ad_impression for linked apps. Manual logging is opt-in so one
// this is what surfaces ad revenue in Firebase/GA4. Ad callbacks fire on the Unity main thread // shown ad does not become two GA4 ad_impression events.
// (RaiseAdEventsOnUnityMainThread = true), so logging straight to analytics is safe.
private void LogAdImpression(AdFormat format, AdValue value) private void LogAdImpression(AdFormat format, AdValue value)
{ {
if (!logManualAdImpressionEvents) return;
_analytics?.LogEvent(AnalyticsEvents.AdImpression, new Dictionary<string, object> _analytics?.LogEvent(AnalyticsEvents.AdImpression, new Dictionary<string, object>
{ {
[AnalyticsParams.AdPlatform] = "AdMob", [AnalyticsParams.AdPlatform] = "AdMob",
@@ -736,4 +742,4 @@ namespace Darkmatter.Services.Ads
LoadStateChanged?.Invoke(format, state); LoadStateChanged?.Invoke(format, state);
} }
} }
} }

View File

@@ -161,7 +161,7 @@ namespace Darkmatter.Services.Analytics
if (dur >= 0f) p[AnalyticsParams.DurationSeconds] = dur; if (dur >= 0f) p[AnalyticsParams.DurationSeconds] = dur;
_analytics.LogEvent(AnalyticsEvents.DrawingCompleted, p); _analytics.LogEvent(AnalyticsEvents.DrawingCompleted, p);
// Companion to GA4's level_start (custom name — GA4's own pair would be level_end). // Companion to GA4's level_start.
_analytics.LogEvent(AnalyticsEvents.LevelComplete, new Dictionary<string, object> _analytics.LogEvent(AnalyticsEvents.LevelComplete, new Dictionary<string, object>
{ {
[AnalyticsParams.LevelName] = s.TemplateId, [AnalyticsParams.LevelName] = s.TemplateId,
@@ -176,15 +176,21 @@ namespace Darkmatter.Services.Analytics
if (PlayerPrefs.GetInt(AllContentKey, 0) == 1) return; // once ever if (PlayerPrefs.GetInt(AllContentKey, 0) == 1) return; // once ever
PlayerPrefs.SetInt(AllContentKey, 1); PlayerPrefs.SetInt(AllContentKey, 1);
PlayerPrefs.Save(); PlayerPrefs.Save();
_analytics.LogEvent(AnalyticsEvents.AllContentCompleted, _analytics.LogEvent(AnalyticsEvents.AllContentCompleted, new Dictionary<string, object>
AnalyticsParams.CompletionCount, s.CompletedCount.ToString()); {
[AnalyticsParams.CompletionCount] = s.CompletedCount,
});
} }
private void OnGallerySaveCompleted(GallerySaveCompletedSignal s) private void OnGallerySaveCompleted(GallerySaveCompletedSignal s)
{ {
_analytics.LogEvent(AnalyticsEvents.GallerySaveCompleted, AnalyticsParams.Success, s.Success ? "true" : "false");
// Prefer the id carried by the signal: art-book saves happen with no active drawing. // Prefer the id carried by the signal: art-book saves happen with no active drawing.
string drawingId = string.IsNullOrEmpty(s.TemplateId) ? _activeDrawingId ?? string.Empty : s.TemplateId; string drawingId = string.IsNullOrEmpty(s.TemplateId) ? _activeDrawingId ?? string.Empty : s.TemplateId;
_analytics.LogEvent(AnalyticsEvents.GallerySaveCompleted, new Dictionary<string, object>
{
[AnalyticsParams.DrawingId] = drawingId,
[AnalyticsParams.Success] = s.Success ? 1 : 0,
});
_analytics.LogEvent(AnalyticsEvents.DrawingSaved, new Dictionary<string, object> _analytics.LogEvent(AnalyticsEvents.DrawingSaved, new Dictionary<string, object>
{ {
[AnalyticsParams.DrawingId] = drawingId, [AnalyticsParams.DrawingId] = drawingId,

View File

@@ -14,6 +14,7 @@ MonoBehaviour:
m_EditorClassIdentifier: Core::Darkmatter.Core.Data.Static.Features.DrawingTemplate.DrawingTemplateSO m_EditorClassIdentifier: Core::Darkmatter.Core.Data.Static.Features.DrawingTemplate.DrawingTemplateSO
id: Bag id: Bag
displayName: Bag displayName: Bag
difficultyOverride: 0
defaultThumbnail: {fileID: 8766740682603709380, guid: ecad1a66623031f4a91dbcee6f10a295, type: 3} defaultThumbnail: {fileID: 8766740682603709380, guid: ecad1a66623031f4a91dbcee6f10a295, type: 3}
drawingPrefab: {fileID: 8396209140419971077, guid: ab15e2395fec7be429926e140d9f4a61, type: 3} drawingPrefab: {fileID: 8396209140419971077, guid: ab15e2395fec7be429926e140d9f4a61, type: 3}
coloringPrefab: {fileID: 222817150442217502, guid: b8b22ebdfe861214c8edef5e46743323, type: 3} coloringPrefab: {fileID: 222817150442217502, guid: b8b22ebdfe861214c8edef5e46743323, type: 3}

View File

@@ -68,7 +68,20 @@ MonoBehaviour:
- rid: 570818657416118287 - rid: 570818657416118287
- rid: 570818657416118288 - rid: 570818657416118288
m_RuntimeSettings: m_RuntimeSettings:
m_List: [] m_List:
- rid: 7752762179098771456
- rid: 7752762179098771457
- rid: 7752762179098771459
- rid: 7752762179098771462
- rid: 7752762179098771464
- rid: 7752762179098771466
- rid: 7752762179098771468
- rid: 7752762179098771472
- rid: 7752762179098771476
- rid: 3114554777721110529
- rid: 3114554777721110530
- rid: 570818657416118282
- rid: 570818657416118283
m_AssetVersion: 10 m_AssetVersion: 10
m_ObsoleteDefaultVolumeProfile: {fileID: 0} m_ObsoleteDefaultVolumeProfile: {fileID: 0}
m_RenderingLayerNames: m_RenderingLayerNames: