feat: integrate Firebase Analytics, add Google Maps dependencies, and expose new GA4 metric API endpoints.

This commit is contained in:
Van Leemput Dayron
2026-01-02 17:10:03 +01:00
parent 5a682bb6d7
commit a9c3087f53
6 changed files with 304 additions and 6 deletions

View File

@@ -169,10 +169,180 @@ app.MapGet("/api/metrics/general", async (
Console.WriteLine($"Error: {ex}");
return Results.Problem($"Analytics API Error: {ex.Message}");
}
})
.WithName("GetGeneralMetrics")
.WithOpenApi();
// 3. Tech Overview (OS & App Version)
// GET /api/metrics/tech?from=x&to=y
app.MapGet("/api/metrics/tech", async (
[FromServices] AnalyticsDataService service,
[FromQuery] string? from,
[FromQuery] string? to) =>
{
var startDate = from ?? "30daysAgo";
var endDate = to ?? "today";
// Request for OS
var requestOS = new RunReportRequest
{
Property = $"properties/{ga4PropertyId}",
DateRanges = new List<DateRange> { new DateRange { StartDate = startDate, EndDate = endDate } },
Dimensions = new List<Dimension> { new Dimension { Name = "operatingSystem" } },
Metrics = new List<Metric> { new Metric { Name = "activeUsers" } }
};
// Request for App Version
var requestVersion = new RunReportRequest
{
Property = $"properties/{ga4PropertyId}",
DateRanges = new List<DateRange> { new DateRange { StartDate = startDate, EndDate = endDate } },
Dimensions = new List<Dimension> { new Dimension { Name = "appVersion" } },
Metrics = new List<Metric> { new Metric { Name = "activeUsers" } } // use active users to see version adoption
};
try
{
var responseOS = await service.Properties.RunReport(requestOS, $"properties/{ga4PropertyId}").ExecuteAsync();
var responseVersion = await service.Properties.RunReport(requestVersion, $"properties/{ga4PropertyId}").ExecuteAsync();
var osData = responseOS.Rows?.Select(row => new {
os = row.DimensionValues[0].Value,
users = int.Parse(row.MetricValues[0].Value)
}) ?? Enumerable.Empty<object>();
var versionData = responseVersion.Rows?.Select(row => new {
version = row.DimensionValues[0].Value,
users = int.Parse(row.MetricValues[0].Value)
}) ?? Enumerable.Empty<object>();
return Results.Ok(new { operatingSystems = osData, appVersions = versionData });
}
catch (Exception ex)
{
return Results.Problem($"Analytics API Error: {ex.Message}");
}
})
.WithName("GetTechOverview")
.WithOpenApi();
// 4. Top Events
// GET /api/metrics/events?from=x&to=y
app.MapGet("/api/metrics/events", async (
[FromServices] AnalyticsDataService service,
[FromQuery] string? from,
[FromQuery] string? to) =>
{
var startDate = from ?? "30daysAgo";
var endDate = to ?? "today";
var request = new RunReportRequest
{
Property = $"properties/{ga4PropertyId}",
DateRanges = new List<DateRange> { new DateRange { StartDate = startDate, EndDate = endDate } },
Dimensions = new List<Dimension> { new Dimension { Name = "eventName" } },
Metrics = new List<Metric> { new Metric { Name = "eventCount" }, new Metric { Name = "activeUsers" } },
OrderBys = new List<OrderBy> { new OrderBy { Desc = true, Metric = new MetricOrderBy { MetricName = "eventCount" } } },
Limit = 20
};
try
{
var response = await service.Properties.RunReport(request, $"properties/{ga4PropertyId}").ExecuteAsync();
var result = response.Rows?.Select(row => new {
eventName = row.DimensionValues[0].Value,
count = int.Parse(row.MetricValues[0].Value),
users = int.Parse(row.MetricValues[1].Value)
}) ?? Enumerable.Empty<object>();
return Results.Ok(result);
}
catch (Exception ex)
{
return Results.Problem($"Analytics API Error: {ex.Message}");
}
})
.WithName("GetTopEvents")
.WithOpenApi();
// 5. Top Screens
// GET /api/metrics/screens?from=x&to=y
app.MapGet("/api/metrics/screens", async (
[FromServices] AnalyticsDataService service,
[FromQuery] string? from,
[FromQuery] string? to) =>
{
var startDate = from ?? "30daysAgo";
var endDate = to ?? "today";
var request = new RunReportRequest
{
Property = $"properties/{ga4PropertyId}",
DateRanges = new List<DateRange> { new DateRange { StartDate = startDate, EndDate = endDate } },
// GA4 uses 'unifiedScreenName' or 'pagePath' depending on setup, usually 'unifiedScreenName' for apps
Dimensions = new List<Dimension> { new Dimension { Name = "unifiedScreenName" } },
Metrics = new List<Metric> { new Metric { Name = "screenPageViews" }, new Metric { Name = "activeUsers" } },
OrderBys = new List<OrderBy> { new OrderBy { Desc = true, Metric = new MetricOrderBy { MetricName = "screenPageViews" } } },
Limit = 20
};
try
{
var response = await service.Properties.RunReport(request, $"properties/{ga4PropertyId}").ExecuteAsync();
var result = response.Rows?.Select(row => new {
screenName = row.DimensionValues[0].Value,
views = int.Parse(row.MetricValues[0].Value),
users = int.Parse(row.MetricValues[1].Value)
}) ?? Enumerable.Empty<object>();
return Results.Ok(result);
}
catch (Exception ex)
{
return Results.Problem($"Analytics API Error: {ex.Message}");
}
})
.WithName("GetTopScreens")
.WithOpenApi();
// 6. User Retention (New vs Returning)
// GET /api/metrics/retention?from=x&to=y
app.MapGet("/api/metrics/retention", async (
[FromServices] AnalyticsDataService service,
[FromQuery] string? from,
[FromQuery] string? to) =>
{
var startDate = from ?? "30daysAgo";
var endDate = to ?? "today";
var request = new RunReportRequest
{
Property = $"properties/{ga4PropertyId}",
DateRanges = new List<DateRange> { new DateRange { StartDate = startDate, EndDate = endDate } },
Dimensions = new List<Dimension> { new Dimension { Name = "newVsReturning" } },
Metrics = new List<Metric> { new Metric { Name = "activeUsers" }, new Metric { Name = "sessions" } }
};
try
{
var response = await service.Properties.RunReport(request, $"properties/{ga4PropertyId}").ExecuteAsync();
var result = response.Rows?.Select(row => new {
type = row.DimensionValues[0].Value,
users = int.Parse(row.MetricValues[0].Value),
sessions = int.Parse(row.MetricValues[1].Value)
}) ?? Enumerable.Empty<object>();
return Results.Ok(result);
}
catch (Exception ex)
{
return Results.Problem($"Analytics API Error: {ex.Message}");
}
})
.WithName("GetUserRetention")
.WithOpenApi();
app.Run();
// Helper to format GA4 YYYYMMDD to YYYY-MM-DD