Skip to main content
Give users control over what communications they receive and how you use their data. This guide explains how to capture, store, and respect user preferences in Zixflow.

What are User Preferences?

User preferences are choices that users make about how they want to interact with your product and what communications they want to receive from you. They’re essentially permission settings and opt-in/opt-out controls that put users in the driver’s seat. Think of preferences as the contract between you and your users about communication boundaries. You’re asking: “How can we reach you, and what do you want to hear about?” They’re answering: “Here’s what I’m comfortable with.”

The Simple Definition

User preferences are settings that control:
  • Which channels you can use to reach them (email yes, SMS no)
  • What types of messages they want to receive (product updates yes, promotions no)
  • How frequently they want to hear from you (daily, weekly, monthly)
  • When you can reach them (respect quiet hours)
Examples:
  • “Send me product updates via email, but no promotional offers”
  • “I want push notifications for important alerts only, not every comment”
  • “Don’t contact me between 10 PM and 7 AM”
  • “Send me a weekly digest instead of individual emails”

Why User Preferences Exist

From the user’s perspective:
  • Control: “I decide what lands in my inbox, not you”
  • Relevance: “Only send me things I care about”
  • Respect: “Don’t wake me up at 2 AM with a promotional push”
  • Trust: “You’re asking my permission, not assuming it”
From your perspective:
  • Legal compliance: GDPR, CAN-SPAM, CCPA require opt-out mechanisms
  • Better engagement: People who opt IN engage more than those who were auto-enrolled
  • Deliverability: Fewer spam complaints = better inbox placement rates
  • Brand reputation: Respecting preferences = users trust you more
  • Reduced noise: Only message people who want to hear from you

The Lifecycle of User Preferences

1. Default state (new user):
// When user signs up
{
  email_marketing: null,           // Not asked yet
  push_notifications: null,        // Not asked yet
  transactional_email: true        // Always on by default
}
2. First permission request (right time, right place):
App: "Get notified when your team mentions you in comments"
User: [Taps "Allow"]

Updated preferences:
{
  push_notifications: true         // User opted in
}
3. Granular control (preference center):
User visits settings → Preference Center
Toggles:
  ✅ Product updates (email)
  ❌ Promotional offers (email)
  ✅ Security alerts (email)
  ✅ @mentions (push)
  ❌ New follower (push)
  
Updated preferences:
{
  email_product_updates: true,
  email_promotions: false,
  email_security: true,
  push_mentions: true,
  push_followers: false
}
4. Refinement over time (user adjusts):
User clicks "Unsubscribe" in email footer
→ Taken to preference page
→ Can unsubscribe from all, or just this category
→ Preferences updated immediately

Types of Preference Controls

1. Channel-level (all-or-nothing per channel):
  • “Send me emails: YES / NO”
  • “Send me push notifications: YES / NO”
  • Simple, but inflexible
2. Category-level (granular by topic):
  • “Send me promotional emails: YES / NO”
  • “Send me product update emails: YES / NO”
  • “Send me transactional emails: ALWAYS (can’t opt out)”
  • Better: users stay subscribed to what they care about
3. Frequency-level (how often):
  • “Send me daily digest” (bundle all updates into one email)
  • “Send me weekly summary”
  • “Send me each notification as it happens”
  • Best: prevents notification fatigue
4. Time-based (when to send):
  • “Quiet hours: 10 PM - 7 AM” (no notifications during sleep)
  • “Send digest at 9 AM every Monday”
  • “Only send during business hours”
  • Respectful: messages arrive when user is ready

The Golden Rule of Preferences

Ask once, respect forever. When a user says “no” to something:
  • ✅ Honor it immediately (no “are you sure?” nagging)
  • ✅ Store it permanently (don’t ask again)
  • ✅ Apply it everywhere (all campaigns respect this preference)
  • ❌ Don’t try to sneak around it (“technically this is a different type of email”)
When a user says “yes”:
  • ✅ Confirm their choice clearly
  • ✅ Let them change their mind easily
  • ✅ Don’t abuse the privilege (just because they said yes to product updates doesn’t mean spam them daily)

Why Preferences Matter

For users:
  • Control inbox fatigue (opt out of promotional emails, keep transactional ones)
  • Choose communication channels (email yes, SMS no)
  • Set frequency limits (daily digests, not every event)
For you:
  • Better engagement (only message people who want to hear from you)
  • Compliance (GDPR, CAN-SPAM, CCPA require opt-out mechanisms)
  • Deliverability (fewer spam complaints = better inbox placement)

Types of Preferences

1. Channel Preferences (What to Reach Them On)

Definition: Which communication channels the user accepts messages through. Each channel has its own opt-out field and timestamp stored on the user profile. Channel opt-out fields:
ChannelFieldDefault state
Emailemail_opt_outUNKNOWN (pending confirmation)
SMSsms_opt_outNOT_OPTED_OUT
WhatsAppwhatsapp_opt_outNOT_OPTED_OUT
RCSrcs_opt_outNOT_OPTED_OUT
Pushpush_opt_outNOT_OPTED_OUT
Each field uses one of three values:
  • 1NOT_OPTED_OUT: user is reachable (default for SMS/WhatsApp/RCS/Push)
  • 2OPTED_OUT: user explicitly opted out — all sends suppressed
  • 3UNKNOWN: intent not yet established (default for Email)
Each channel also stores an _opt_out_at timestamp:
// User opts out of SMS
Zixflow.instance.setProfileAttributes({
  'sms_opt_out': 2,
  'sms_opt_out_at': DateTime.now().toIso8601String(),
});

// User opts out of push
Zixflow.instance.setProfileAttributes({
  'push_opt_out': 2,
  'push_opt_out_at': DateTime.now().toIso8601String(),
});

// User confirms email opt-in
Zixflow.instance.setProfileAttributes({
  'email_opt_out': 1,  // NOT_OPTED_OUT
});
Important: Email defaults to UNKNOWN rather than NOT_OPTED_OUT because email requires explicit confirmation before you can assume consent (GDPR). All other channels default to NOT_OPTED_OUT since they require an explicit action (push permission grant, phone number submission) to receive messages at all.

2. Category Preferences (What Type of Messages)

Definition: What topics or types of content the user wants to receive. Category preferences are custom attributes — you define the categories that make sense for your product and store them as profile attributes. Example:
Zixflow.instance.setProfileAttributes({
  'subscribed_to_promotions': false,      // No sales/discounts
  'subscribed_to_product_updates': true,  // Product news yes
  'subscribed_to_newsletter': true,       // Weekly newsletter yes
  'subscribed_to_transactional': true,    // Order updates (always on)
});
Why categories matter:
  • User might want product updates but not promotional emails
  • Transactional messages (order confirmations, password resets) typically can’t be opted out
  • GDPR requires granular control (not just “all or nothing”)

3. Frequency Preferences (How Often to Message)

Definition: Controls how often users receive non-critical messages. Like categories, frequency preferences are custom attributes you define and check when building campaigns. Example:
Zixflow.instance.setProfileAttributes({
  'email_frequency': 'daily_digest',  // immediate | daily_digest | weekly_digest | never
  'push_frequency': 'immediate',
  'max_emails_per_week': 3,
});

4. User Suppression (Block All Channels)

Suppression is a server-side lifecycle event that blocks all outbound messages for a user across every channel, regardless of their individual opt-out settings.
Lifecycle EventEffect
User SuppressedSets is_suppressed = true on profile — no messages sent on any channel
User UnsuppressedClears the flag — message delivery resumes
When to use suppression:
  • User requests complete silence (GDPR “right to be forgotten” equivalent)
  • Account fraud/abuse detected
  • Account is past-due / in bad standing
Suppression is distinct from channel opt-out: opt-out is per-channel and set by the user, suppression is workspace-controlled and blocks everything.

Capturing Preferences

Method 1: In-App Preference Center

Best for: Letting users manage their own preferences (GDPR requirement) Example UI:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  Notification Preferences
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Email Preferences:
☑ Product updates & new features
☑ Weekly newsletter
☐ Promotions & discounts
☑ Order & account notifications

Push Notifications:
☑ New messages
☑ Friend activity
☐ Daily summary

[Save Preferences]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Implementation:
// User clicks "Save Preferences"
function savePreferences() {
  const prefs = {
    subscribed_to_product_updates: document.getElementById('product_updates').checked,
    subscribed_to_newsletter: document.getElementById('newsletter').checked,
    subscribed_to_promotions: document.getElementById('promotions').checked,
    subscribed_to_transactional: true,  // Always on
    
    push_new_messages: document.getElementById('push_messages').checked,
    push_friend_activity: document.getElementById('push_activity').checked,
    push_daily_summary: document.getElementById('push_summary').checked
  };
  
  Zixflow.setProfileAttributes(prefs);
  
  // Also track that they updated preferences
  Zixflow.track('Updated Preferences', { changes: prefs });
}

Best for: One-click opt-out from email campaigns (CAN-SPAM requirement) Example flow:
  1. User receives promotional email
  2. Clicks “Unsubscribe” link at bottom
  3. Lands on preference page: “You’ve unsubscribed from promotional emails”
  4. Option to manage granular preferences or unsubscribe from all
Implementation:
// Unsubscribe page loads
const urlParams = new URLSearchParams(window.location.search);
const userId = urlParams.get('user_id');
const category = urlParams.get('category');  // e.g., "promotions"

// Immediately unsubscribe
Zixflow.identify({ 
  userId: userId,
  traits: {
    [`subscribed_to_${category}`]: false,
    unsubscribed_at: new Date().toISOString()
  }
});

Zixflow.track('Unsubscribed', { 
  category: category,
  source: 'email_link' 
});

// Show confirmation
document.getElementById('message').innerText = 
  `You've been unsubscribed from ${category} emails.`;

Method 3: Onboarding Preference Collection

Best for: Setting preferences early (before first campaign) Example onboarding screen:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  How would you like to hear from us?
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

☑ Email me about new features (weekly)
☑ Push notifications for messages (real-time)
☐ SMS me about special offers

[Continue]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Why this works:
  • Sets expectations early (“we’ll email you weekly”)
  • Reduces future unsubscribes (they opted in knowingly)
  • Better engagement (only contact people who agreed)

Respecting Preferences in Campaigns

Transactional vs. Marketing Messages

Transactional messages (can’t be opted out):
  • Order confirmations
  • Password resets
  • Account security alerts
  • Billing notifications
Why: User needs these to use your service (GDPR carve-out) Marketing messages (must respect opt-out):
  • Newsletters
  • Promotional emails
  • Feature announcements
  • Re-engagement campaigns
Implementation:
// Transactional: Always send (ignore preferences)
sendEmail({
  to: user.email,
  template: 'order_confirmation',
  bypass_preferences: true,  // Send even if opted out of marketing
  data: { order_id: 'ord_123' }
});

// Marketing: Check preferences first
if (user.subscribed_to_promotions && user.preferences_email) {
  sendEmail({
    to: user.email,
    template: 'weekly_deals',
    respect_preferences: true,
    data: { deals: [...] }
  });
}

Default Preferences (What If User Hasn’t Set Any?)

Conservative approach (better for compliance):
// Default user to opted OUT of marketing, IN for transactional
const defaultPreferences = {
  subscribed_to_promotions: false,       // Opt-in required
  subscribed_to_newsletter: false,       // Opt-in required
  subscribed_to_product_updates: false,  // Opt-in required
  subscribed_to_transactional: true,     // Always on
  
  preferences_email: true,               // Email enabled (but only transactional)
  preferences_push: false,               // Opt-in required
  preferences_sms: false                 // Opt-in required
};
Aggressive approach (better for engagement, riskier legally):
// Default user to opted IN to everything
const defaultPreferences = {
  subscribed_to_promotions: true,    // Opt-out to stop
  subscribed_to_newsletter: true,    // Opt-out to stop
  subscribed_to_product_updates: true,
  subscribed_to_transactional: true,
  
  preferences_email: true,
  preferences_push: true,            // Requires device token
  preferences_sms: false             // SMS usually requires explicit opt-in
};
When to use each:
  • Conservative: EU users (GDPR), healthcare, financial services
  • Aggressive: Existing customers, B2B, low-regulation industries

Preference Syncing Across Devices

Challenge: User opts out of push notifications on phone, but still gets them on tablet. Solution: Preferences are stored at the user profile level, not device level. How it works:
// User opts out on iPhone
Zixflow.setProfileAttributes({
  preferences_push: false  // Applies to ALL devices
});

// Next campaign:
// → iPhone: No push (opted out)
// → iPad: No push (opted out)
// → Web: No push (opted out)
Device-specific preferences (if needed):
// Opt out on THIS device only
Zixflow.setDeviceAttributes({
  push_enabled: false  // Only this device
});

GDPR (Europe)

Requirements: ✅ Clear consent before marketing communications
✅ Easy way to withdraw consent (unsubscribe link)
✅ Granular control (not just “all or nothing”)
✅ Explicit opt-in for sensitive categories (health, finance)
Implementation:
  • Default users to opted OUT
  • Require checkbox during signup: “I agree to receive marketing emails”
  • Provide preference center with granular controls

CAN-SPAM (United States)

Requirements: ✅ Unsubscribe link in every marketing email
✅ Honor opt-out within 10 business days
✅ Clear “From” name (not deceptive)
✅ Accurate subject line
Implementation:
  • Include unsubscribe link in email footer
  • Immediately set subscribed_to_promotions = false on click
  • Exclude opted-out users from all marketing campaigns

CCPA (California)

Requirements: ✅ Allow users to opt out of data “sale” (sharing for advertising)
✅ Provide “Do Not Sell My Personal Information” link
✅ Honor opt-out immediately
Implementation:
// User clicks "Do Not Sell"
Zixflow.setProfileAttributes({
  ccpa_opt_out: true,  // Don't share data with ad platforms
  opted_out_at: new Date().toISOString()
});

Next: Use the API for server-side tracking → API Reference