Invitation Usage Tracking
View SourceThis guide explains how to use Usher's invitation tracking features to monitor entity interactions with invitation links and gather usage statistics.
With Usher, you can track any domain entity's usage of invitation links, such as users, companies, devices, etc.
Overview
Usher provides two levels of invitation tracking:
- Basic tracking - Simple joined count for backward compatibility
- Entity tracking - Detailed tracking of different entity types and their actions
Configuration
First, configure the valid entity types and actions in your config/config.exs:
config :usher,
repo: MyApp.Repo,
validations: %{
invitation_usage: %{
# Required for entity tracking
valid_usage_entity_types: [:user, :company, :device],
valid_usage_actions: [:visited, :registered, :activated]
}
}Database Setup
Add the invitation tracking tables to your database:
# Create a migration file
defmodule MyApp.Repo.Migrations.CreateUsherTables do
use Ecto.Migration
import Usher.Migration
def change do
create_usher_invitations_table()
create_usher_invitation_usages_table()
end
endEntity Tracking
Track Invitation Usage
Track when entities interact with your invitation links:
# Track with invitation struct
{:ok, usage} = Usher.track_invitation_usage(
invitation,
:user, # entity type
"user_123", # entity ID
:registered, # action
%{ # optional metadata
plan: "premium",
ip: "192.168.1.1",
user_agent: "Mozilla/5.0...",
campaign: "summer_2024"
}
)
# Track with token string
{:ok, usage} = Usher.track_invitation_usage(
"abc123token",
:company,
"company_456",
:visited,
%{referrer: "google.com"}
)Common Tracking Patterns
Track page visits:
# When someone clicks the invitation link
Usher.track_invitation_usage(token, :user, user_id, :visited, %{
ip: request_ip,
user_agent: user_agent,
timestamp: DateTime.utc_now()
})Track registrations:
# When user completes registration
Usher.track_invitation_usage(invitation, :user, new_user.id, :registered, %{
plan: selected_plan,
signup_method: "email"
})Track activations:
# When user activates their account
Usher.track_invitation_usage(invitation, :user, user.id, :activated, %{
activation_method: "email_confirmation"
})Getting Usage Statistics
List All Usage Records
# Get all usage records for an invitation
usages = Usher.list_invitation_usages(invitation)
# Filter by entity type
user_usages = Usher.list_invitation_usages(invitation, entity_type: :user)
# Filter by action
registrations = Usher.list_invitation_usages(invitation, action: :registered)
# Multiple filters with pagination
recent_visits = Usher.list_invitation_usages(invitation,
entity_type: :user,
action: :visited,
limit: 10
)Analyze Unique Entities
# Get unique entities that used the invitation
entities = Usher.list_invitation_usages_by_unique_entity(invitation)
# Returns: [{"user_123", [usage_records...]}, {"company_456", [usage_records...]}]
# Filter for specific actions
registered_entities = Usher.list_invitation_usages_by_unique_entity(
invitation,
action: :registered
)Check Individual Entity Usage
# Check if a specific entity used the invitation
has_used = Usher.entity_used_invitation?(invitation, :user, "user_123")
# Check for specific action
has_registered = Usher.entity_used_invitation?(invitation, :user, "user_123", :registered)Analytics Examples
Conversion Funnel Analysis
defmodule MyApp.InvitationAnalytics do
def conversion_funnel(invitation) do
visits = Usher.list_invitation_usages(invitation, action: :visited)
registrations = Usher.list_invitation_usages(invitation, action: :registered)
activations = Usher.list_invitation_usages(invitation, action: :activated)
%{
visits: length(visits),
registrations: length(registrations),
activations: length(activations),
visit_to_registration_rate: length(registrations) / max(length(visits), 1),
registration_to_activation_rate: length(activations) / max(length(registrations), 1)
}
end
endEntity Type Breakdown
defmodule MyApp.InvitationAnalytics do
def entity_breakdown(invitation) do
invitation
|> Usher.list_invitation_usages()
|> Enum.group_by(& &1.entity_type)
|> Enum.map(fn {entity_type, usages} ->
{entity_type, length(usages)}
end)
|> Enum.into(%{})
end
endMetadata Analysis
defmodule MyApp.InvitationAnalytics do
def referrer_sources(invitation) do
invitation
|> Usher.list_invitation_usages(action: :visited)
|> Enum.map(& get_in(&1.metadata, ["referrer"]))
|> Enum.filter(& &1)
|> Enum.frequencies()
end
def plan_preferences(invitation) do
invitation
|> Usher.list_invitation_usages(action: :registered)
|> Enum.map(& get_in(&1.metadata, ["plan"]))
|> Enum.filter(& &1)
|> Enum.frequencies()
end
endError Handling
Common error scenarios and handling:
case Usher.track_invitation_usage(token, :user, "123", :registered) do
{:ok, usage} ->
# Success
usage
{:error, :invalid_token} ->
# Token doesn't exist
{:error, :invitation_expired} ->
# Invitation has expired
{:error, :invalid_entity_type} ->
# Entity type not in valid_usage_entity_types config
{:error, :invalid_action} ->
# Action not in valid_usage_actions config
{:error, %Ecto.Changeset{}} ->
# Database constraint violation (e.g., duplicate tracking)
endBest Practices
- Use meaningful entity types - Choose types that match your business model
- Track the full journey - Record visits, registrations, and activations
- Include relevant metadata - Store context that helps with analysis
- Handle duplicates gracefully - The system prevents duplicate tracking automatically
- Validate tokens before tracking - Always check if invitation is valid and not expired
- Use filtering for large datasets - Apply entity_type and action filters for performance
Performance Considerations
- Use database indexes on frequently queried fields
- Consider pagination for large usage datasets
- Cache frequently accessed statistics
- Use database-level aggregations for complex analytics
This tracking system provides comprehensive insights into how your invitation links are being used, helping you optimize your conversion funnels and understand user behavior patterns.