Inviting Users
The ContactsManager SDK provides a powerful invite system that enables controlled app growth, user acquisition tracking, and viral loop implementation. The invite service supports multiple distribution methods and provides detailed analytics for measuring growth effectiveness.
Accessing the Invite Service
The invite service is accessed through the ContactsManager shared instance:
Swift
React Native
Kotlin
Objective-C
import ContactsManager
let cm = ContactsService. shared
let inviteService = cm. invites
// Access invite properties and methods
let inviteCode = await inviteService. code
let inviteLink = await inviteService. link
let remainingInvites = await inviteService. remaining ()
Invite Code Management
Getting Current Invite Code
Retrieve the user’s current invite code, or create one if none exists:
Swift
React Native
Kotlin
Objective-C
let inviteCode = await cm. invites . code
if let code = inviteCode {
print ( "Your invite code: \( code ) " )
// Display code to user for sharing
} else {
print ( "Unable to get invite code" )
}
Getting Invite Link
Retrieve the full invite URL for web-based sharing:
Swift
React Native
Kotlin
Objective-C
let inviteLink = await cm. invites . link
if let link = inviteLink {
print ( "Share this link: \( link ) " )
// Use link for social sharing, email, etc.
} else {
print ( "Unable to get invite link" )
}
Creating New Invites
Manually create a new invite (useful for generating fresh codes):
Swift
React Native
Kotlin
Objective-C
let newInvite = await cm. invites . createInvite ()
if let invite = newInvite {
print ( "New invite code: \( invite. inviteCode ) " )
print ( "New invite URL: \( invite. inviteUrl ) " )
print ( "Expires at: \( invite. expiresAt ) " )
} else {
print ( "Failed to create new invite" )
}
Invite Validation and Redemption
Validating Invite Codes
Validate an invite code before allowing redemption:
Swift
React Native
Kotlin
Objective-C
let validation = await cm. invites . validateCode ( code : "ABC123" )
if let result = validation {
if result.valid {
print ( "Valid invite from: \( result. inviter ? . displayName ?? "Unknown" ) " )
print ( "Organization: \( result. organizationName ?? "N/A" ) " )
print ( "Remaining invites: \( result. remainingInvites ?? 0 ) " )
} else {
print ( "Invalid invite: \( result. message ) " )
}
} else {
print ( "Unable to validate invite code" )
}
Redeeming Invites
Redeem an invite code for a new user:
Swift
React Native
Kotlin
Objective-C
let success = await cm. invites . redeemInvite (
code : "ABC123" ,
for : "new_user_id_123"
)
if success {
print ( "Invite redeemed successfully" )
// Proceed with user onboarding
} else {
print ( "Failed to redeem invite" )
}
Getting Invite Details (Public)
Get detailed invite information for landing pages (doesn’t require authentication):
Swift
React Native
Kotlin
Objective-C
let details = await cm. invites . getInviteDetails ( for : "ABC123" )
if let inviteDetails = details {
if inviteDetails.valid {
print ( "Invited by: \( inviteDetails. inviter ? . displayName ?? "Someone" ) " )
print ( "Join \( inviteDetails. organizationName ?? "this app" ) " )
} else {
print ( "Invite expired or invalid" )
}
}
Invite Analytics and Tracking
Checking Remaining Invites
Get the number of invites the current user has left:
Swift
React Native
Kotlin
Objective-C
let remaining = await cm. invites . remaining ()
print ( "You have \( remaining ) invites remaining" )
// Use this to show invite limits in UI
if remaining > 0 {
// Show invite button
} else {
// Show "no invites left" message
}
Getting Invited Users
Retrieve the list of users invited by the current user:
Swift
React Native
Kotlin
Objective-C
let invitedUsers = await cm. invites . invited ()
print ( "You've invited \( invitedUsers. count ) users:" )
for user in invitedUsers {
print ( "- \( user. displayName ?? "Unknown" ) " )
}
// Use for showing invite success and building social proof
Finding Who Invited You
Get information about who invited the current user:
Swift
React Native
Kotlin
Objective-C
let inviter = await cm. invites . invitedBy ()
if let whoInvitedMe = inviter {
print ( "You were invited by: \( whoInvitedMe. displayName ?? "Unknown" ) " )
// Show connection to inviter in onboarding
// Enable features that connect inviter and invitee
} else {
print ( "You joined without an invite" )
}
Bulk Email Invitations
Checking Email Invite Availability
Verify if bulk email invites are available for your organization:
Swift
React Native
Kotlin
Objective-C
let emailAvailable = await cm. invites . isBulkInviteEmailAvailable ()
if emailAvailable {
// Show email invite options
print ( "Email invites are available" )
} else {
// Show setup instructions or alternative invite methods
print ( "Email invites require domain verification" )
}
Sending Bulk Email Invites
Send invite emails to multiple contacts at once:
Swift
React Native
Kotlin
Objective-C
// Get contacts to invite (from recommendations or user selection)
let contactsToInvite = await cm. people . fetch (
matching : [. suggestedInvite ],
limit : 10
)
let emailBody = """
Hi there!
I've been using this amazing app and thought you'd love it too.
It's helped me stay organized and connect with friends.
Join me and let's explore it together!
Best,
[Your name]
"""
let result = await cm. invites . sendBulkInviteEmails (
contacts : contactsToInvite,
emailBody : emailBody
)
if let response = result {
if response.success {
print ( "Sent \( response. emailsSent ) invites successfully" )
if ! response.failedEmails. isEmpty {
print ( "Failed to send to: \( response. failedEmails . joined ( separator : ", " ) ) " )
}
} else {
print ( "Email invite failed: \( response. message ) " )
}
}
Building Invite Flows
Basic Invite Sharing
Create a simple invite sharing interface:
Swift
React Native
Kotlin
Objective-C
struct InviteView : View {
@State private var inviteCode: String ?
@State private var inviteLink: String ?
@State private var remainingInvites: Int = 0
@State private var isLoading = true
var body: some View {
VStack ( spacing : 20 ) {
if isLoading {
ProgressView ( "Loading invite info..." )
} else {
VStack ( spacing : 16 ) {
Text ( "Invite Friends" )
. font (. title2 )
. fontWeight (. bold )
Text ( "You have \( remainingInvites ) invites remaining" )
. foregroundColor (. secondary )
if let code = inviteCode {
VStack {
Text ( "Your Invite Code" )
. font (. headline )
Text (code)
. font (. title )
. fontWeight (. bold )
. padding ()
. background (Color. gray . opacity ( 0.1 ))
. cornerRadius ( 8 )
}
}
if let link = inviteLink {
ShareLink (
item : URL ( string : link) ! ,
message : Text ( "Join me on this amazing app!" )
) {
Label ( "Share Invite Link" , systemImage : "square.and.arrow.up" )
. frame ( maxWidth : . infinity )
. padding ()
. background (Color. blue )
. foregroundColor (. white )
. cornerRadius ( 8 )
}
}
}
}
}
. padding ()
. onAppear {
loadInviteInfo ()
}
}
private func loadInviteInfo () async {
let cm = ContactsService. shared
async let code = cm. invites . code
async let link = cm. invites . link
async let remaining = cm. invites . remaining ()
let (inviteCode, inviteLink, remainingCount) = await (code, link, remaining)
DispatchQueue. main . async {
self . inviteCode = inviteCode
self . inviteLink = inviteLink
self . remainingInvites = remainingCount
self . isLoading = false
}
}
}
Invite Redemption Flow
Handle invite code redemption during onboarding:
Swift
React Native
Kotlin
Objective-C
struct InviteRedemptionView : View {
@State private var inviteCode = ""
@State private var isValidating = false
@State private var validationResult: ValidateInviteCodeResponse ?
@State private var showError = false
var body: some View {
VStack ( spacing : 20 ) {
Text ( "Enter Invite Code" )
. font (. title2 )
. fontWeight (. bold )
TextField ( "Invite Code" , text : $inviteCode)
. textFieldStyle ( RoundedBorderTextFieldStyle ())
. autocapitalization (. allCharacters )
. onChange ( of : inviteCode) { newValue in
if newValue. count == 6 {
validateInvite ()
}
}
if isValidating {
ProgressView ( "Validating..." )
}
if let result = validationResult {
if result.valid {
VStack {
Text ( "✅ Valid Invite" )
. foregroundColor (. green )
. fontWeight (. bold )
if let inviter = result.inviter {
Text ( "Invited by: \( inviter. displayName ?? "Unknown" ) " )
}
if let orgName = result.organizationName {
Text ( "Organization: \( orgName ) " )
}
Button ( "Join App" ) {
redeemInvite ()
}
. buttonStyle (. borderedProminent )
}
} else {
Text ( "❌ \( result. message ) " )
. foregroundColor (. red )
}
}
}
. padding ()
. alert ( "Error" , isPresented : $showError) {
Button ( "OK" ) { }
} message : {
Text ( "Unable to validate invite code" )
}
}
private func validateInvite () {
guard inviteCode. count == 6 else { return }
isValidating = true
Task {
let result = await ContactsService. shared . invites . validateCode ( code : inviteCode)
DispatchQueue. main . async {
self . isValidating = false
self . validationResult = result
if result == nil {
self . showError = true
}
}
}
}
private func redeemInvite () {
// Implement redemption logic with your user ID
Task {
let success = await ContactsService. shared . invites . redeemInvite (
code : inviteCode,
for : "current_user_id"
)
if success {
// Navigate to main app
} else {
// Show error
}
}
}
}
Invite Analytics Dashboard
Display invite performance and user relationships:
Swift
React Native
Kotlin
Objective-C
struct InviteAnalyticsView : View {
@State private var invitedUsers: [Contact] = []
@State private var invitedBy: Contact ?
@State private var remainingInvites: Int = 0
@State private var isLoading = true
var body: some View {
NavigationView {
List {
Section ( "Your Invite Status" ) {
HStack {
Text ( "Remaining Invites" )
Spacer ()
Text ( " \( remainingInvites ) " )
. fontWeight (. bold )
}
if let inviter = invitedBy {
HStack {
Text ( "Invited by" )
Spacer ()
Text (inviter. displayName ?? "Unknown" )
}
}
}
if ! invitedUsers. isEmpty {
Section ( "People You've Invited ( \( invitedUsers. count ) )" ) {
ForEach (invitedUsers, id : \. contactId ) { user in
HStack {
VStack ( alignment : . leading ) {
Text (user. displayName ?? "Unknown" )
. fontWeight (. medium )
if let email = user.cmContact ? .emailAddresses. first ? . value {
Text (email)
. font (. caption )
. foregroundColor (. secondary )
}
}
Spacer ()
Image ( systemName : "checkmark.circle.fill" )
. foregroundColor (. green )
}
}
}
}
}
. navigationTitle ( "Invite Analytics" )
. refreshable {
await loadAnalytics ()
}
}
. onAppear {
Task {
await loadAnalytics ()
}
}
}
private func loadAnalytics () async {
let cm = ContactsService. shared
async let invited = cm. invites . invited ()
async let inviter = cm. invites . invitedBy ()
async let remaining = cm. invites . remaining ()
let (invitedList, inviterContact, remainingCount) = await (invited, inviter, remaining)
DispatchQueue. main . async {
self . invitedUsers = invitedList
self . invitedBy = inviterContact
self . remainingInvites = remainingCount
self . isLoading = false
}
}
}
Best Practices
Invite Limit Management
Start Conservative : Begin with 3-5 invites per user to create scarcity
Reward Quality : Give additional invites to users whose invitees become active
Monitor Growth : Adjust limits based on server capacity and user acquisition goals
User Experience
Clear Value Proposition : Explain why users should invite friends
Social Proof : Show mutual connections and successful invitations
Immediate Connection : Help invited users connect with their inviter quickly
Growth Optimization
Track Conversion : Monitor invite-to-signup and invite-to-active-user rates
A/B Test Messages : Experiment with different invite email templates
Analyze Networks : Identify users who bring high-quality new members
Privacy Considerations
Minimal Exposure : Invite codes contain no personal information
User Control : Allow users to disable invite notifications
Data Retention : Implement policies for invite relationship data
Error Handling
Common error scenarios and how to handle them:
Swift
React Native
Kotlin
Objective-C
// Handle invite validation errors
let validation = await cm. invites . validateCode ( code : userInput)
if let result = validation {
if ! result.valid {
switch result.message {
case "Invalid invite code format" :
// Show format help (6 characters, alphanumeric)
break
case "Invite code expired" :
// Suggest requesting new invite
break
case "Invite limit reached" :
// Explain invite limits
break
default :
// Generic error message
break
}
}
} else {
// Network or service error
// Show retry option
}
// Handle bulk email errors
let emailResult = await cm. invites . sendBulkInviteEmails (
contacts : selectedContacts,
emailBody : customMessage
)
if let result = emailResult {
if ! result.success {
if result.message. contains ( "verified email sending domain" ) {
// Guide user to domain verification
} else if result.message. contains ( "Invalid request data" ) {
// Check contact data quality
}
}
}
For more information about implementing invite features in your application, visit contactsmanager.io .