Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
364 commits
Select commit Hold shift + click to select a range
b961740
Update chart to take more horizontal space
kean Jul 26, 2025
12a5265
Improve more menu alignment
kean Jul 26, 2025
dd8575e
More breezing room
kean Jul 26, 2025
3a193fe
Show top 5
kean Jul 26, 2025
6b4ca65
Simplify TopListItemView requirements
kean Jul 26, 2025
c7cfdbe
Add previews for top list items
kean Jul 26, 2025
5269b0c
Add cache for mock data
kean Jul 26, 2025
a09bb44
Simplify mock data generation
kean Jul 26, 2025
7965ebc
Set min height for bars
kean Jul 26, 2025
761bea5
Add initial implementation
kean Jul 26, 2025
75c9540
Rework await Task.detached(priority: .userInitiated) {
kean Jul 26, 2025
dc9e83f
Add zoom
kean Jul 26, 2025
60233d3
Refactor
kean Jul 26, 2025
5448589
Fix reloading in dark mode
kean Jul 26, 2025
25f1740
Improve colors
kean Jul 26, 2025
3c8057a
Add initial hover support
kean Jul 26, 2025
9e523c4
Extract interactive-map-template
kean Jul 26, 2025
b6c08dd
Improve tooltip view
kean Jul 26, 2025
e7a34c9
Refactor
kean Jul 26, 2025
2045459
Clear map selection when you stop hovering
kean Jul 26, 2025
e1e2a20
lintfix
kean Jul 26, 2025
b9c3a7e
Add TopListCard previews
kean Jul 26, 2025
c365399
Improve TopListLocationRowView design
kean Jul 26, 2025
c4c4982
Cleanup isNavigationDisabled
kean Jul 26, 2025
866ea88
Add CountriesMapView and more (#24688)
kean Jul 26, 2025
42d04ec
Remove map dependency
kean Jul 26, 2025
cbb5334
Fix animation in TrafficTabView
kean Jul 26, 2025
1d706d6
Disable zoom in InteractiveMapView
kean Jul 26, 2025
15104a3
Improve sizing of TopListItemViews
kean Jul 26, 2025
7e1d7f9
More design changes
kean Jul 27, 2025
4530aba
Implement chart animation on first load
kean Jul 27, 2025
64ac0cd
Fix LineChartView sometimes showing zero in the middle
kean Jul 27, 2025
0eb093d
Fix clipping of AM label
kean Jul 27, 2025
3fa2584
Simplify selection on map
kean Jul 27, 2025
82cb8cc
Fix an issue with SVGWebView not reloading if killed
kean Jul 27, 2025
470a04e
Fix retain cycles
kean Jul 27, 2025
77f0cc3
Extract CountriesMapData
kean Jul 27, 2025
f4aee7d
Remove isNavigationDisabled
kean Jul 27, 2025
c78a96f
Use gradient in LineChartView
kean Jul 27, 2025
f212953
Use gradient in BarChartView
kean Jul 27, 2025
2ed4517
Use gradient for Top List also
kean Jul 27, 2025
76de9e5
More compelling gradients
kean Jul 27, 2025
ebe9277
Add significant data points, add pulsating anmation
kean Jul 27, 2025
ae92f82
Add significant data point to bar chart also
kean Jul 27, 2025
121e577
use rounded in badges
kean Jul 27, 2025
132d71b
Extract SignificantPointAnnotation
kean Jul 27, 2025
580ee9a
Rework ARchive
kean Jul 27, 2025
b099dcb
Add tap animation for TopListItemView
kean Jul 27, 2025
2de8171
Add context menus
kean Jul 27, 2025
f336dce
Add context menus for items
kean Jul 27, 2025
b2bbf45
Remove isComparisonPeriodEnabled
kean Jul 27, 2025
2b37ca6
Remove isNavigationDisabled
kean Jul 27, 2025
c6044a4
Remove odd looking background when tapping Top List items
kean Jul 27, 2025
8048739
Implement pulsating for overlay too
kean Jul 27, 2025
306f436
Rework shapes
kean Jul 27, 2025
432fb6b
Fix showmore lyout
kean Jul 27, 2025
b5e791f
Nicer badges
kean Jul 27, 2025
b5d64bf
Nicer video display
kean Jul 27, 2025
da6a92a
Add support for external links
kean Jul 27, 2025
d8700d4
Add more performance reserveSpace
kean Jul 27, 2025
7bc168b
Add initial TopListScreenView
kean Jul 27, 2025
8503336
Tap on card to open entire screen
kean Jul 27, 2025
052357b
Rename TopListViewModel
kean Jul 27, 2025
89aa65c
Add TopListChartData.Metrics
kean Jul 27, 2025
732872f
Rename TopListResponse
kean Jul 27, 2025
5175e58
Rename TopListItemProtocol
kean Jul 27, 2025
615321c
Rename TopListItem
kean Jul 27, 2025
28aad13
Rename TopListData
kean Jul 27, 2025
96e4180
Add secondaryBackground
kean Jul 27, 2025
471295e
Add more eleborate background
kean Jul 27, 2025
97a028d
Simplify background
kean Jul 27, 2025
e861548
Add date range control
kean Jul 27, 2025
ea6ab12
Add CSV export
kean Jul 27, 2025
e1e5716
Optimize CSV export
kean Jul 27, 2025
b708d18
Fix sorting for top list items to ensure stable ordering
kean Jul 27, 2025
871992d
use ShareLink
kean Jul 27, 2025
d25afa0
Darker empty row
kean Jul 27, 2025
b3ba255
Fix navigation from top list
kean Jul 27, 2025
a908fcc
lintfix
kean Jul 27, 2025
9e5faa0
Fix export – use CSV extensio
kean Jul 27, 2025
ee616ae
Fix items not loading in mock service
kean Jul 27, 2025
1b05926
Add TopListScreenView (#24689)
kean Jul 27, 2025
c995974
Remove Calendar.current usages
kean Jul 27, 2025
9670c57
Update unit tests
kean Jul 27, 2025
3665928
Smaller heading in ListScreenView
kean Jul 27, 2025
51dc63a
Remove broken LazyVStack and simplify interactive-map-template
kean Jul 27, 2025
3a094bf
Fix selection for country map
kean Jul 27, 2025
f776290
PRevent ScrollOffsetModifier to firing when no changes are made
kean Jul 27, 2025
af5b2da
Show only 5 recent years on a trend ma[
kean Jul 27, 2025
bdab226
Fix StatsDateRangeFormatter ntot showing last year
kean Jul 27, 2025
9bc446b
Update StatsDateRangeFormatterTests tests to be independant of year
kean Jul 27, 2025
65a43f6
Load aatars with higher quality
kean Jul 27, 2025
9d8c04d
Cleanup StatsServiceRemoteV2 extensions
kean Jul 27, 2025
7839786
Fix TopList being tappable on mock data
kean Jul 27, 2025
1394018
Smaller ChartValuesSummaryView
kean Jul 27, 2025
d0b7b8e
Add documentation links
kean Jul 27, 2025
de99096
Add reporting time zone to the bottom of the tab
kean Jul 27, 2025
0cadbf8
Nicer empty state view
kean Jul 27, 2025
23ac4c0
Slight chart card redesign
kean Jul 27, 2025
81b916c
Fix compilation error on earlier Xcode versions
kean Jul 27, 2025
99dcab7
New Stats: Bugfix (#24690)
kean Jul 27, 2025
62b8feb
Better ChartCard header
kean Jul 28, 2025
1ce45e5
Update StandaloneChartCard
kean Jul 28, 2025
912409d
Center top list screen header vertically
kean Jul 28, 2025
07656f9
Add initial StatsViewModel
kean Jul 28, 2025
756dab9
Remove unused comparisonRangeText
kean Jul 28, 2025
9e0a74b
Add initial ChartCardCustomizationView
kean Jul 28, 2025
ffda2a9
Rework where config is created
kean Jul 28, 2025
5cc8165
Add initial delete widget support
kean Jul 28, 2025
a021c52
Add support for deleting charts
kean Jul 28, 2025
d612a3c
Rename delete
kean Jul 28, 2025
4e3c300
Rework how we save configuration
kean Jul 28, 2025
ee9d6c5
Move seletedMetric to ViewModel
kean Jul 28, 2025
37523e6
Save ChartType persistently
kean Jul 28, 2025
7737d7a
Improve gradients
kean Jul 28, 2025
9501856
Cleanup
kean Jul 28, 2025
616599a
Fix significantPointAnnotations in line chart
kean Jul 28, 2025
7d09b5a
Rework ChartCardCustomizationView
kean Jul 28, 2025
d207105
Add TopListCardCustomizationView
kean Jul 28, 2025
eb29c5f
Refactor TopListCardCustomizationView
kean Jul 28, 2025
fed7c3a
Remove StatsViewModel from TopListCard
kean Jul 28, 2025
f1805e8
Improve chart editig
kean Jul 28, 2025
dcf8f8d
Improve add card style
kean Jul 28, 2025
c98b745
Implement Move Card feature
kean Jul 28, 2025
3151302
Simplify EditCardMenuContent
kean Jul 28, 2025
a8d16a5
Remove unused strings
kean Jul 28, 2025
ae2765d
Update menus org
kean Jul 28, 2025
e211261
SwiftLint
kean Jul 28, 2025
13c8784
Cleanup
kean Jul 28, 2025
eab0806
New Stats: Customization (#24692)
kean Jul 28, 2025
77a60bc
Better PlaceholderRowView
kean Jul 28, 2025
3e83ce2
Better empty rows
kean Jul 28, 2025
ac251cb
Lighter bars in dark mode
kean Jul 28, 2025
b3f8edd
Lighter bars in dark mode
kean Jul 28, 2025
790b5ba
Better contrast on a map
kean Jul 28, 2025
6dc781e
Fix map selection
kean Jul 28, 2025
e1ab7fe
Better loading state for avatars
kean Jul 28, 2025
721e710
Reorg
kean Jul 28, 2025
cebacc1
Cleanup
kean Jul 28, 2025
f6a40af
Fix StatsPeriodUnit crash
kean Jul 28, 2025
49267b2
Fix navigateToTopListScreen
kean Jul 28, 2025
70e6a4b
Fix navigation title not appearing instantly
kean Jul 28, 2025
c57add0
Dsable sharing for now
kean Jul 28, 2025
7e783a0
Cleanup
kean Jul 28, 2025
0f62079
Store preset persistently
kean Jul 28, 2025
7d4923f
Add reset all settings for convenience
kean Jul 28, 2025
8ae6a03
Minor iPad improvemnets
kean Jul 28, 2025
90995e8
Add caching
kean Jul 28, 2025
4b432fd
New Stats: Misc (#24693)
kean Jul 28, 2025
a694b77
Add new menus to enable/disable stats
kean Jul 28, 2025
b0578df
Rework how we show the new stats
kean Jul 28, 2025
633bf9b
Add SafeAreaHostingController to workaround safe area issue
kean Jul 28, 2025
de4bf86
Add extra top padding
kean Jul 28, 2025
8741ec2
Add a way to show mock data
kean Jul 28, 2025
530ef42
Cleanup StatsHostingViewController
kean Jul 28, 2025
4280dc7
Add configureModernStyle to FilterTabBar
kean Jul 28, 2025
ef41a0e
Shorten interval for editing
kean Jul 28, 2025
8031e64
Update l10n
kean Jul 28, 2025
b969e37
Add delay when showing tip
kean Jul 28, 2025
cb7f3c2
Fix an issue with interpolation when there is only one data point
kean Jul 28, 2025
8f84b4a
Increase listHeaderView spacing
kean Jul 28, 2025
ca2262a
Add l10n
kean Jul 28, 2025
2787422
New Stats: Integration (#24694)
kean Jul 28, 2025
36b69a5
Fix long button names
kean Jul 29, 2025
262b3e6
Fix TopListCard in AuthorStatsView
kean Jul 29, 2025
38a2778
Improve formatting in date range control
kean Jul 29, 2025
a6b1e06
Add CardGradientBackground
kean Jul 29, 2025
2d988cc
Fix an issue with filter not passed to TopListScreen
kean Jul 29, 2025
33ce879
Fix minimum size for subscriber rows
kean Jul 29, 2025
f5b4585
Fix an issue with authors posts showing wrong data on show more
kean Jul 29, 2025
86c14bb
Improve mock data
kean Jul 29, 2025
b966b51
Show debug options in Stats in the debug menu
kean Jul 29, 2025
95257fe
Simplify filter tab bar
kean Jul 29, 2025
867c6ef
Fix y domain on BarChartView
kean Jul 29, 2025
eec554f
Add subscriber details
kean Jul 29, 2025
f0b52be
Reverse raw data
kean Jul 29, 2025
2643f6c
use regular context for date formatting
kean Jul 29, 2025
1cc49e4
Update historic data
kean Jul 29, 2025
1cb558a
Initial iPad support
kean Jul 30, 2025
4bc5345
Remove insets from the CardModifier itself
kean Jul 30, 2025
8c8bdc4
Add a reusable method to set horizontal inset
kean Jul 30, 2025
454ddba
Cleanup
kean Jul 30, 2025
f882ce8
Move range controls to hte top on iPad
kean Jul 30, 2025
cce9bc6
More improvements on iPad
kean Jul 30, 2025
af12ae1
Fix how trailingItemGroups is communicated back the to main VC
kean Jul 30, 2025
887069e
Cleanup buttons
kean Jul 30, 2025
af309f0
Show more cards on iPad
kean Jul 30, 2025
c0e6f3b
Improve design on PostStatsView
kean Jul 30, 2025
3d4d80f
Save StandaloneChart type persistently; update PostStatsView on iPad
kean Jul 30, 2025
1958ee3
Add empty state
kean Jul 30, 2025
75a44a8
Update AuthorStatsView
kean Jul 30, 2025
1a6c134
SHow date navigation at the top
kean Jul 30, 2025
2a8aab6
Update ChartDataListView
kean Jul 30, 2025
35017b0
Update ExternalLinkStatsView
kean Jul 30, 2025
6485a37
Update referrers
kean Jul 30, 2025
2408e56
TopListScreenView to support iPad
kean Jul 30, 2025
732823e
Update TopListScreenView
kean Jul 30, 2025
1789b3a
Reduce trailing in TopListItemView
kean Jul 30, 2025
33ab026
Fix realtime view
kean Jul 30, 2025
002a32e
More spacing for metrics on iPad
kean Jul 30, 2025
a80f1f8
Improve ChartValueTooltipView
kean Jul 30, 2025
6e89474
Pink for likes
kean Jul 30, 2025
da44ea7
Improve menu design
kean Jul 30, 2025
4abaae8
Update ChartDataListView design
kean Jul 30, 2025
225dcb1
More improvemnets
kean Jul 30, 2025
7775104
Slightly rounder bars
kean Jul 30, 2025
5be0daf
Update ChartCard again
kean Jul 30, 2025
f5e0c6f
Change last5 to last3 years and use monthly granularity
kean Jul 30, 2025
77e4f1f
Update tess
kean Jul 30, 2025
76798c8
New Stats: iPad (#24701)
kean Jul 30, 2025
b2ec41c
Improve average badge design
kean Jul 30, 2025
3ee0fb7
Cleanup
kean Jul 30, 2025
169b409
Fix an issue with selection line going beyond the chart range
kean Jul 30, 2025
36c15ed
Extract ChartAverageLine
kean Jul 30, 2025
a8b38d5
Improve tab over view anmations
kean Jul 30, 2025
1e4b912
Remove fatalError
kean Jul 30, 2025
bbf926b
Add StatsEvent and StatsTracker
kean Jul 30, 2025
3f49427
Add additional events for customization
kean Jul 30, 2025
40c8343
Add mapping to WPAnalyticsEvent
kean Jul 30, 2025
53c9e53
Add new_stats key to .statsAccessed
kean Jul 30, 2025
074b3a1
Cleanup urlErrorType
kean Jul 30, 2025
08796e3
Do no track CancellationError
kean Jul 30, 2025
6a031ab
New Stats: Analytics (#24702)
kean Jul 30, 2025
ca3ef07
Improve heatmap colors for dark mode
kean Jul 30, 2025
e09508f
Improve annotations
kean Jul 30, 2025
7e129b3
Add dynamic type support
kean Jul 30, 2025
433ad9d
Improve line chart scaling
kean Jul 30, 2025
b9c2602
Add voice over support
kean Jul 30, 2025
60f27a8
New Stats: Accessibility (#24703)
kean Jul 30, 2025
5245588
Fix an issue with new stats menu not shownig up on iphone
kean Jul 31, 2025
7bc44ac
Less visible TopList empty views
kean Jul 31, 2025
5cb7d9d
Fix tab size in overview
kean Jul 31, 2025
dcfd948
Fix insets on top list
kean Jul 31, 2025
8e3afc6
Fix disabling of navigation button in top bar
kean Jul 31, 2025
a70c149
Add a bit of top inset
kean Jul 31, 2025
8abd79a
Fix tests build
kean Jul 31, 2025
b7a8380
Remove animations from add chart button
kean Jul 31, 2025
29190a3
Lower h spacing on ipad
kean Jul 31, 2025
7511764
Remove animations from ChartValuesSummaryView
kean Jul 31, 2025
03f1736
Selection tooltip no longer moves with content
kean Aug 1, 2025
5984fdc
Remove delay when showing details
kean Aug 1, 2025
b823743
Use black for tint
kean Aug 1, 2025
b6613f4
Update articles
kean Aug 4, 2025
5231fa9
Fix 642: invalid hourly data
kean Aug 4, 2025
942972c
Update time zone design
kean Aug 4, 2025
9166c2c
Update WordPressKit to point to the latest commit
kean Aug 4, 2025
7c0e716
Revert "Fix minimum size for subscriber rows"
kean Aug 4, 2025
1fff562
Replace fatalError with assertionFailure
kean Aug 5, 2025
031a359
Merge branch 'trunk' into feature/jetpack-stats
kean Aug 5, 2025
5b51ea1
Merge branch 'trunk' into feature/jetpack-stats
kean Aug 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Modules/Package.resolved

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 12 additions & 1 deletion Modules/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ let package = Package(
.library(name: "AsyncImageKit", targets: ["AsyncImageKit"]),
.library(name: "DesignSystem", targets: ["DesignSystem"]),
.library(name: "FormattableContentKit", targets: ["FormattableContentKit"]),
.library(name: "JetpackStats", targets: ["JetpackStats"]),
.library(name: "JetpackStatsWidgetsCore", targets: ["JetpackStatsWidgetsCore"]),
.library(name: "NotificationServiceExtensionCore", targets: ["NotificationServiceExtensionCore"]),
.library(name: "ShareExtensionCore", targets: ["ShareExtensionCore"]),
Expand Down Expand Up @@ -49,7 +50,7 @@ let package = Package(
.package(url: "https://github.com/wordpress-mobile/NSURL-IDN", revision: "b34794c9a3f32312e1593d4a3d120572afa0d010"),
.package(
url: "https://github.com/wordpress-mobile/WordPressKit-iOS",
revision: "2b7d4f6acf2641b671c66b20873f5935f22210ed"
revision: "440d94e3a3d6f9f39035a371984e088a2fb42a32"
),
.package(url: "https://github.com/zendesk/support_sdk_ios", from: "8.0.3"),
// We can't use wordpress-rs branches nor commits here. Only tags work.
Expand Down Expand Up @@ -93,6 +94,14 @@ let package = Package(
// Set to v5 to avoid @Sendable warnings and errors
swiftSettings: [.swiftLanguageMode(.v5)]
),
.target(
name: "JetpackStats",
dependencies: [
"WordPressUI",
.product(name: "WordPressKit", package: "WordPressKit-iOS"),
],
resources: [.process("Resources")]
),
.target(name: "JetpackStatsWidgetsCore", swiftSettings: [.swiftLanguageMode(.v5)]),
.target(
name: "ShareExtensionCore",
Expand Down Expand Up @@ -171,6 +180,7 @@ let package = Package(
dependencies: ["AsyncImageKit", "WordPressUI", "WordPressShared"],
resources: [.process("Resources")]
),
.testTarget(name: "JetpackStatsTests", dependencies: ["JetpackStats"]),
.testTarget(name: "JetpackStatsWidgetsCoreTests", dependencies: [.target(name: "JetpackStatsWidgetsCore")], swiftSettings: [.swiftLanguageMode(.v5)]),
.testTarget(name: "DesignSystemTests", dependencies: [.target(name: "DesignSystem")], swiftSettings: [.swiftLanguageMode(.v5)]),
.testTarget(
Expand Down Expand Up @@ -276,6 +286,7 @@ enum XcodeSupport {
"DesignSystem",
"BuildSettingsKit",
"FormattableContentKit",
"JetpackStats",
"JetpackStatsWidgetsCore",
"NotificationServiceExtensionCore",
"SFHFKeychainUtils",
Expand Down
15 changes: 15 additions & 0 deletions Modules/Sources/JetpackStats/Analytics/MockStatsTracker.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Foundation

/// A no-op implementation of StatsTracker for testing and development
final class MockStatsTracker: StatsTracker, Sendable {
static let shared = MockStatsTracker()

private init() {}

func send(_ event: StatsEvent, properties: [String: String]) {
#if DEBUG
// In debug builds, print events to console for debugging
debugPrint("[StatsTracker] Event: \(event) \(properties)")
#endif
}
}
191 changes: 191 additions & 0 deletions Modules/Sources/JetpackStats/Analytics/StatsEvent.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
import Foundation

/// Analytics events for tracking user interactions within the Stats module
///
/// IMPORTANT: Do not include personally identifiable information (PII) in analytics events.
/// This includes but is not limited to:
/// - User IDs, author IDs, or any unique identifiers
/// - Email addresses
/// - URLs that might contain sensitive information
/// - Post IDs or content identifiers
///
/// Instead, track only:
/// - Event types and categories
/// - Navigation sources
/// - UI states and configurations
/// - Aggregated metrics
public enum StatsEvent {
// MARK: - Screen View Events

/// Main stats screen shown
case statsMainScreenShown

/// Traffic tab shown
case trafficTabShown

/// Realtime tab shown
case realtimeTabShown

/// Subscribers tab shown
case subscribersTabShown

/// Post details screen shown
case postDetailsScreenShown

/// Author stats screen shown
case authorStatsScreenShown

/// Archive stats screen shown
case archiveStatsScreenShown

/// External link stats screen shown
case externalLinkStatsScreenShown

/// Referrer stats screen shown
case referrerStatsScreenShown

// MARK: - Date Range Events

/// Date range preset selected
/// - Parameters:
/// - "selected_preset": The preset selected (e.g., "last_7_days", "last_28_days", "last_90_days", "last_365_days")
case dateRangePresetSelected

/// Custom date range selected
/// - Parameters:
/// - "start_date": Start date in ISO format
/// - "end_date": End date in ISO format
case customDateRangeSelected

// MARK: - Card Events

/// Card shown on screen
/// - Parameters:
/// - "card_type": Type of card (e.g., "chart", "top_list")
/// - "configuration": Card configuration details (e.g., metrics, item type)
case cardShown

/// Card added to dashboard
/// - Parameters:
/// - "card_type": Type of card (e.g., "chart", "top_list")
case cardAdded

/// Card removed from dashboard
/// - Parameters:
/// - "card_type": Type of card
case cardRemoved

// MARK: - Chart Events

/// Chart type changed
/// - Parameters:
/// - "from_type": Previous chart type (e.g., "line", "bar")
/// - "to_type": New chart type
case chartTypeChanged

/// Chart metric selected
/// - Parameters:
/// - "metric": The metric selected (e.g., "visitors", "views", "likes")
case chartMetricSelected

// MARK: - List Events

/// Top list item tapped
/// - Parameters:
/// - "item_type": Type of item (e.g., "posts_and_pages", "authors", "locations", "referrers")
/// - "metric": The metric being sorted by
case topListItemTapped

// MARK: - Navigation Events

/// Stats tab selected
/// - Parameters:
/// - "tab_name": Name of the tab selected
/// - "previous_tab": Name of the previous tab
case statsTabSelected

// MARK: - Error Events

/// Error encountered
/// - Parameters:
/// - "error_type": Type of error (e.g., "network", "parsing", "permission")
/// - "error_code": Specific error code if available
/// - "screen": Where the error occurred
case errorEncountered
}

// MARK: - StatsTracker Protocol

/// Protocol for tracking analytics events in the Stats module
public protocol StatsTracker: Sendable {
/// Send an analytics event
/// - Parameters:
/// - event: The event to track
/// - properties: Additional properties for the event
func send(_ event: StatsEvent, properties: [String: String])
}

// MARK: - StatsTracker Convenience

extension StatsTracker {
/// Convenience method to send events without properties
func send(_ event: StatsEvent) {
send(event, properties: [:])
}
}

// MARK: - Private Extensions

extension DateIntervalPreset {
/// Analytics tracking name for the preset
var analyticsName: String {
switch self {
case .today: "today"
case .thisWeek: "this_week"
case .thisMonth: "this_month"
case .thisQuarter: "this_quarter"
case .thisYear: "this_year"
case .last7Days: "last_7_days"
case .last28Days: "last_28_days"
case .last30Days: "last_30_days"
case .last90Days: "last_90_days"
case .last6Months: "last_6_months"
case .last12Months: "last_12_months"
case .last3Years: "last_3_years"
case .last10Years: "last_10_years"
}
}
}

extension TopListItemType {
/// Analytics tracking name for the item type
var analyticsName: String {
switch self {
case .postsAndPages: "posts_and_pages"
case .authors: "authors"
case .referrers: "referrers"
case .locations: "locations"
case .videos: "videos"
case .externalLinks: "external_links"
case .searchTerms: "search_terms"
case .fileDownloads: "file_downloads"
case .archive: "archive"
}
}
}

extension SiteMetric {
/// Analytics tracking name for the metric
var analyticsName: String {
switch self {
case .views: "views"
case .visitors: "visitors"
case .likes: "likes"
case .comments: "comments"
case .posts: "posts"
case .timeOnSite: "time_on_site"
case .bounceRate: "bounce_rate"
case .downloads: "downloads"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import Foundation

extension StatsTracker {
/// Convenience method to track errors with automatic type detection
/// - Parameters:
/// - error: The error to track
/// - screen: The screen where the error occurred
func trackError(_ error: Error, screen: String) {
let errorType: String
let errorCode = (error as NSError).code

// Determine error type based on the error instance
switch error {
case let urlError as URLError:
errorType = urlErrorType(urlError)
case is DecodingError:
errorType = "parsing"
case is CancellationError:
return
default:
// Check for common error domains
let nsError = error as NSError
switch nsError.domain {
case NSCocoaErrorDomain:
errorType = "cocoa_\(errorCode)"
case NSURLErrorDomain:
errorType = "url_\(errorCode)"
default:
errorType = "unknown"
}
}

send(.errorEncountered, properties: [
"error_type": errorType,
"error_code": "\(errorCode)",
"screen": screen
])
}

/// Determine specific network error type
private func urlErrorType(_ error: URLError) -> String {
switch error.code {
case .notConnectedToInternet: "network_offline"
case .timedOut: "network_timeout"
case .cannotFindHost, .cannotConnectToHost: "network_host_unreachable"
case .networkConnectionLost: "network_connection_lost"
case .dnsLookupFailed: "network_dns_failed"
case .httpTooManyRedirects: "network_too_many_redirects"
case .resourceUnavailable: "network_resource_unavailable"
case .dataNotAllowed: "network_data_not_allowed"
case .secureConnectionFailed: "network_ssl_failed"
default: "other"
}
}
}
15 changes: 15 additions & 0 deletions Modules/Sources/JetpackStats/Cards/CardConfigurationDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Foundation

enum MoveDirection {
case up
case down
case top
case bottom
}

@MainActor
protocol CardConfigurationDelegate: AnyObject {
func saveConfiguration(for card: any TrafficCardViewModel)
func deleteCard(_ card: any TrafficCardViewModel)
func moveCard(_ card: any TrafficCardViewModel, direction: MoveDirection)
}
9 changes: 9 additions & 0 deletions Modules/Sources/JetpackStats/Cards/CardViewModel.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import Foundation

@MainActor
protocol TrafficCardViewModel: AnyObject {
var id: UUID { get }
var dateRange: StatsDateRange { get set }
var isEditing: Bool { get set }
var configurationDelegate: CardConfigurationDelegate? { get set }
}
Loading