Goal Friction Impact (GFI) Tracking in iOS and iPadOS with Appxiom framework
Manual Integration: Define goals and track user completion rates with two simple API calls.
Appxiom framework's Goal Friction Impact (GFI) feature enables you to track user journeys through critical app flows and understand how bugs and performance issues impact your business metrics. Define goals for key user flows like signup, purchase, onboarding, or any other, and Appxiom will monitor completion rates, identify friction points, and calculate customer loss when issues occur.
How Goal Friction Impact Works
GFI transforms traditional bug reporting into business intelligence:
- Define Goals: Mark the start and end of important user flows
- Track Completion: Monitor how many users successfully complete each goal
- Identify Friction: Detect when crashes, freezes, API failures or any other issues interrupt user journeys
- Measure Impact: Calculate completion rates, drop-off points, and potential customer loss
- Prioritize Fixes: Focus on bugs that have the highest business impact
Implementing Goal Tracking
Use the beginGoal() and completeGoal() methods to track user journeys through your app's critical flows.
Starting a Goal
- Objective C
- Swift
// Start tracking a signup goal
NSNumber *goalId = [Ax beginGoalAt:self goal:@"user_signup"];
// Start tracking a purchase goal
NSNumber *checkoutGoalId = [Ax beginGoalAt:self goal:@"checkout_process"];
// Start tracking an onboarding goal
NSNumber *onboardingGoalId = [Ax beginGoalAt:self goal:@"user_onboarding"];
// Start tracking a signup goal
let goalId = Ax.beginGoal(at: self, goal: "user_signup")
// Start tracking a purchase goal
let checkoutGoalId = Ax.beginGoal(at: self, goal: "checkout_process")
// Start tracking an onboarding goal
let onboardingGoalId = Ax.beginGoal(at: self, goal: "user_onboarding")
Completing a Goal
- Objective C
- Swift
// Complete the signup goal
[Ax completeGoalAt:self goalId:goalId];
// Complete the checkout goal
[Ax completeGoalAt:self goalId:checkoutGoalId];
// Complete the onboarding goal
[Ax completeGoalAt:self goalId:onboardingGoalId];
// Complete the signup goal
Ax.completeGoal(at: self, goalId: goalId)
// Complete the checkout goal
Ax.completeGoal(at: self, goalId: checkoutGoalId)
// Complete the onboarding goal
Ax.completeGoal(at: self, goalId: onboardingGoalId)
Example: Tracking a Signup Flow
Here's how to implement GFI for a typical user signup process:
- Objective C
- Swift
@interface SignupViewController : UIViewController
@property (nonatomic, strong) NSNumber *signupGoalId;
@end
@implementation SignupViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Begin tracking the signup goal
self.signupGoalId = [Ax beginGoalAt:self goal:@"user_signup"];
}
- (void)onSignupSuccess {
// User successfully completed signup
[Ax completeGoalAt:self goalId:self.signupGoalId];
// Navigate to next screen
DashboardViewController *dashboardVC = [[DashboardViewController alloc] init];
[self.navigationController pushViewController:dashboardVC animated:YES];
}
- (void)onSignupFailure:(NSString *)error {
// Goal will automatically be marked as incomplete
// Appxiom will track this as a friction point
NSLog(@"Signup failed: %@", error);
}
@end
class SignupViewController: UIViewController {
private var signupGoalId: NSNumber?
override func viewDidLoad() {
super.viewDidLoad()
// Begin tracking the signup goal
signupGoalId = Ax.beginGoal(at: self, goal: "user_signup")
}
private func onSignupSuccess() {
// User successfully completed signup
if let goalId = signupGoalId {
Ax.completeGoal(at: self, goalId: goalId)
}
// Navigate to next screen
let dashboardVC = DashboardViewController()
navigationController?.pushViewController(dashboardVC, animated: true)
}
private func onSignupFailure(error: String) {
// Goal will automatically be marked as incomplete
// Appxiom will track this as a friction point
print("Signup failed: \(error)")
}
}
Best Practices for Goal Tracking
1. Choose Meaningful Goals
- Focus on business-critical user flows
- Track complete end-to-end journeys
- Use descriptive goal names
2. Strategic Placement
- Call
beginGoal(at:goal:)at the start of the user flow - Call
completeGoal(at:goalId:)only when the user successfully completes the entire journey - Don't call
completeGoal(at:goalId:)for partial completions
3. Goal Naming Convention
Important: Goal names are automatically filtered and have the following restrictions:
- Only alphanumeric characters (A-Z, a-z, 0-9) and underscores (_) are allowed. All other characters are removed.
- Maximum length is 64 characters. Names longer than 64 characters will be truncated.
// Original goal name → Filtered goal name
"user_registration_flow" → "user_registration_flow" // Underscores preserved
"premium-subscription-purchase" → "premiumsubscriptionpurchase" // Hyphens removed
"first.time.user.onboarding" → "firsttimeuseronboarding" // Dots removed
"user@signup#flow" → "usersignupflow" // Special characters removed
// Length limit example
"very_long_goal_name_that_exceeds_the_maximum_allowed_length_limit_of_64_characters_will_be_truncated"
→ "very_long_goal_name_that_exceeds_the_maximum_allowed_length_li" // Truncated at 64 chars
Best Practices:
// Good: Descriptive, specific, and under 64 characters
Ax.beginGoal(at: self, goal: "user_registration_flow")
Ax.beginGoal(at: self, goal: "premium_subscription_purchase")
Ax.beginGoal(at: self, goal: "first_time_user_onboarding")
// Will be automatically filtered
Ax.beginGoal(at: self, goal: "premium-subscription-purchase") // → "premiumsubscriptionpurchase"
Ax.beginGoal(at: self, goal: "first.time.user.onboarding") // → "firsttimeuseronboarding"
// Avoid: Vague, too granular, or excessively long
Ax.beginGoal(at: self, goal: "button_click")
Ax.beginGoal(at: self, goal: "action")
Frequently Asked Questions (FAQ)
Q: How do I enable Goal Friction Impact tracking in my app?
A: Simply call beginGoal(at:goal:) and completeGoal(at:goalId:) to track user journeys.
Q: Does GFI tracking work in both debug and release builds?
A: Yes, GFI tracking works in both debug and release builds, allowing you to monitor goals during development and in production.
Q: Can I track multiple goals simultaneously for the same user?
A: Yes, you can track multiple goals concurrently. Each beginGoal(at:goal:) call returns a unique ID that you use with completeGoal(at:goalId:).
Q: Are there any restrictions on goal names?
A: Yes, goal names have two restrictions: 1) They are automatically filtered to contain only alphanumeric characters (A-Z, a-z, 0-9) and underscores (_). Other special characters, spaces, and symbols are removed. For example, "user-signup.flow" becomes "usersignupflow", and "user_signup_flow" remains unchanged. 2) Maximum length is 64 characters - names longer than this will be truncated.
Q: What happens if I don't call completeGoal(at:goalId:) for a started goal?
A: Then that goal will be tracked as incomplete, causing inconsistent data to be displayed in Appxiom dashboard.
Q: Can I see goal data in real-time?
A: Yes, goal analytics are available in the Appxiom dashboard in near real-time where you can view data as they are synced from the app.
Q: Can I use GFI with other analytics tools?
A: Yes, GFI can be used alongside other analytics and conversion tracking tools without conflicts.
Q: How do I handle goals that span multiple view controllers?
A: Store the goal ID in a shared location (like a singleton, app delegate, or pass it between view controllers) and call completeGoal(at:goalId:) when the entire flow is finished.