Improving RUM Action Names in .NET MAUI
By default, Datadog RUM tracks user interactions in MAUI apps, but the action names can be cryptic and hard to understand. For example:
tap on BottomNavigationItemView(0x2) on crc646e722b0a9beeeae7.MainActivity
This document explains how to improve action naming for better observability.
The Problem
MAUI uses platform-specific renderers that generate technical class names. Without proper tagging, RUM actions show:
- Android: Obfuscated class names like
crc646e722b0a9beeeae7.MainActivity,BottomNavigationItemView(0x2) - iOS: Similar technical identifiers
These names make it difficult to:
- Understand user behavior in RUM dashboards
- Create meaningful funnels and analytics
- Debug user experience issues
Solution 1: AutomationId Property
The AutomationId property in MAUI provides a way to tag UI elements with human-readable identifiers that Datadog RUM can capture.
How to Use AutomationId
Add the AutomationId property to any interactive MAUI element:
<Button
x:Name="CheckoutButton"
AutomationId="checkout_button"
Text="Checkout"
Clicked="OnCheckoutClicked" />
Naming Conventions
Use snake_case naming that describes the action:
<!-- Good Examples -->
<Button AutomationId="add_to_cart_button" ... />
<Button AutomationId="refresh_products_button" ... />
<Button AutomationId="clear_cart_button" ... />
<Button AutomationId="increase_quantity_button" ... />
<!-- Navigation Tabs -->
<ShellContent AutomationId="tab_products" ... />
<ShellContent AutomationId="tab_cart" ... />
<ShellContent AutomationId="tab_profile" ... />
<!-- Lists and Collections -->
<CollectionView AutomationId="products_list" ... />
<CollectionView AutomationId="cart_items_list" ... />
Benefits
- Readable RUM Actions: Instead of
tap on BottomNavigationItemView(0x2), you gettap on checkout_button - Better Analytics: Easier to create funnels and analyze user behavior
- Consistent Naming: Same identifier works on both Android and iOS
- UI Testing: AutomationId also improves automated testing
Solution 2: Manual RUM Action Tracking
For more control, manually track actions with custom names:
using Datadog.Maui.Rum;
private async void OnCheckoutClicked(object? sender, EventArgs e)
{
// Track with custom name and attributes
Rum.AddAction(RumActionType.Tap, "checkout_button", new Dictionary<string, object>
{
{ "item_count", cartService.ItemCount },
{ "total_amount", cartService.TotalAmount }
});
// Your logic here
await ProcessCheckout();
}
When to Use Manual Tracking
- Complex user flows that need context
- Adding custom attributes to actions
- Tracking non-UI interactions
- Custom events that don’t correspond to UI elements
Solution 3: Hybrid Approach (Recommended)
Combine both approaches for best results:
<!-- Use AutomationId for basic identification -->
<Button
x:Name="CheckoutButton"
AutomationId="checkout_button"
Text="Proceed to Checkout"
Clicked="OnCheckoutClicked" />
private async void OnCheckoutClicked(object? sender, EventArgs e)
{
// Add manual tracking with rich context
Rum.AddAction(RumActionType.Tap, "checkout_initiated", new Dictionary<string, object>
{
{ "item_count", _cartService.ItemCount },
{ "total_amount", _cartService.TotalAmount },
{ "payment_method", selectedPaymentMethod },
{ "has_coupon", !string.IsNullOrEmpty(couponCode) }
});
await ProcessCheckout();
}
This gives you:
- Automatic tracking with readable names (via AutomationId)
- Rich context for important actions (via manual tracking)
- Comprehensive view of user behavior
Best Practices
1. Name Elements Consistently
<!-- Pattern: {action}_{element_type} -->
<Button AutomationId="add_to_cart_button" />
<Button AutomationId="remove_item_button" />
<Button AutomationId="refresh_products_button" />
<!-- Pattern: {section}_{element_type} -->
<CollectionView AutomationId="products_list" />
<CollectionView AutomationId="cart_items_list" />
<!-- Pattern: tab_{tab_name} -->
<ShellContent AutomationId="tab_products" />
<ShellContent AutomationId="tab_cart" />
2. Add Context with Manual Tracking
// Track with business context
Rum.AddAction(RumActionType.Tap, "add_to_cart", new Dictionary<string, object>
{
{ "product_id", product.Id },
{ "product_name", product.Name },
{ "product_price", product.Price },
{ "cart_item_count", _cartService.ItemCount },
{ "is_on_sale", product.IsOnSale }
});
3. Track Key User Flows
Focus on business-critical actions:
// Cart operations
Rum.AddAction(RumActionType.Custom, "add_to_cart", attributes);
Rum.AddAction(RumActionType.Custom, "remove_from_cart", attributes);
Rum.AddAction(RumActionType.Custom, "update_quantity", attributes);
// Checkout flow
Rum.AddAction(RumActionType.Custom, "checkout_initiated", attributes);
Rum.AddAction(RumActionType.Custom, "payment_submitted", attributes);
Rum.AddAction(RumActionType.Custom, "purchase_completed", attributes);
// Search and discovery
Rum.AddAction(RumActionType.Custom, "product_searched", attributes);
Rum.AddAction(RumActionType.Custom, "product_filtered", attributes);
Rum.AddAction(RumActionType.Custom, "product_viewed", attributes);
4. Use Meaningful Attributes
Add attributes that help with analysis:
new Dictionary<string, object>
{
// Business metrics
{ "item_count", 3 },
{ "total_amount", 149.97 },
{ "discount_applied", true },
// User context
{ "is_authenticated", true },
{ "user_tier", "premium" },
// Technical context
{ "network_type", "wifi" },
{ "app_version", "1.2.3" }
}
Example: Complete Cart Implementation
See the sample app for a complete implementation:
XAML (CartPage.xaml):
<Button
AutomationId="checkout_button"
Text="Proceed to Checkout"
Clicked="OnCheckoutClicked" />
<Button
AutomationId="clear_cart_button"
Text="Clear Cart"
Clicked="OnClearCartClicked" />
<Button
AutomationId="increase_quantity_button"
Clicked="OnIncreaseQuantityClicked" />
Code (CartPage.xaml.cs):
private async void OnCheckoutClicked(object? sender, EventArgs e)
{
Rum.AddAction(RumActionType.Tap, "checkout_button", new Dictionary<string, object>
{
{ "item_count", _cartService.ItemCount },
{ "total_amount", _cartService.TotalAmount }
});
await ProcessCheckout();
}
Verifying in Datadog
After implementation:
- Navigate to RUM > Actions in your Datadog dashboard
- Look for readable action names like:
tap on checkout_buttontap on add_to_cart_buttontap on tab_cart
- Click on an action to see custom attributes
- Create funnels using these named actions
Additional Resources
Related Guides: