Skip to content
Tolinku
Tolinku
Sign In Start Free
Use Cases · · 5 min read

Contextual Onboarding: Adapting to User Intent

By Tolinku Staff
|
Tolinku fintech deep linking dashboard screenshot for use cases blog posts

Every user who installs your app has an intent. Someone who tapped an ad for running shoes wants to see running shoes. Someone who followed a friend's referral wants to know what their friend uses the app for. Someone who scanned a QR code at a restaurant wants to see the menu. Contextual onboarding reads this intent from the deep link data and adapts accordingly.

For personalization strategies, see Personalized Onboarding Flows with Deep Link Data. For invite-specific flows, see Invite Link Onboarding: From Invitation to Active User.

Every deep link carries intent signals, even if they're implicit. For a comprehensive look at how contextual deep linking works under the hood, see the Contextual Deep Linking Guide.

Signal Example Parameter Implied Intent
Product category category=running Wants running products
Specific item product_id=abc123 Wants to see this product
Referrer ref=sarah_123 Trusts the referrer
Campaign utm_campaign=summer_sale Interested in deals
Feature feature=workout_tracker Wants this specific capability
Location context store=downtown_branch In-store shopper
Content type content=recipe_collection Interested in recipes

Capturing Intent

async function captureUserIntent() {
  const deferred = await Tolinku.checkDeferredLink();

  if (deferred === null) {
    return { type: 'organic', confidence: 'low' };
  }

  const params = deferred.params;
  const path = deferred.path;

  // Determine intent type and confidence
  if (params.product_id) {
    return {
      type: 'product_specific',
      confidence: 'high',
      product: params.product_id,
      source: params.utm_source,
    };
  }

  if (params.category) {
    return {
      type: 'category_interest',
      confidence: 'medium',
      category: params.category,
      source: params.utm_source,
    };
  }

  if (params.ref) {
    return {
      type: 'referral',
      confidence: 'high',
      referrer: params.ref,
      referrerName: params.referrer_name,
    };
  }

  if (params.utm_campaign) {
    return {
      type: 'campaign',
      confidence: 'medium',
      campaign: params.utm_campaign,
      source: params.utm_source,
    };
  }

  return {
    type: 'deep_link_generic',
    confidence: 'low',
    path: path,
  };
}

Adapting the Flow

Intent-Based Routing

function OnboardingRouter({ intent }) {
  switch (intent.type) {
    case 'product_specific':
      return <ProductFocusedOnboarding intent={intent} />;

    case 'category_interest':
      return <CategoryOnboarding intent={intent} />;

    case 'referral':
      return <ReferralOnboarding intent={intent} />;

    case 'campaign':
      return <CampaignOnboarding intent={intent} />;

    case 'organic':
    default:
      return <StandardOnboarding />;
  }
}

Product-Specific Intent

The user clicked a link to a specific product. Show it immediately, then onboard around it:

function ProductFocusedOnboarding({ intent }) {
  const [phase, setPhase] = useState('product_view');

  return (
    <View>
      {phase === 'product_view' && (
        <ProductPreview
          productId={intent.product}
          onContinue={() => setPhase('signup')}
          ctaText="Sign up to purchase"
        />
      )}

      {phase === 'signup' && (
        <QuickSignup
          context={`Sign up to buy ${intent.productName}`}
          onComplete={() => setPhase('purchase')}
        />
      )}

      {phase === 'purchase' && (
        <ProductPage
          productId={intent.product}
          showPromoBanner={intent.promoCode ? true : false}
        />
      )}
    </View>
  );
}

This flow is: show value, then ask for commitment. The product view gives the user a reason to sign up.

Category Interest

The user came from an ad or content about a specific category. Pre-select their interest:

function CategoryOnboarding({ intent }) {
  return (
    <View>
      <WelcomeScreen
        headline={getCategoryWelcome(intent.category)}
        subtext="Let's set up your experience."
      />

      <AccountCreation />

      {/* Skip "What are you interested in?" — we already know */}
      <CategoryFeed
        category={intent.category}
        preSelected={true}
      />
    </View>
  );
}

function getCategoryWelcome(category) {
  const welcomes = {
    running: 'Ready to find your perfect running gear?',
    cooking: 'Let us help you discover new recipes.',
    fitness: 'Your fitness journey starts here.',
    travel: 'Where are you headed next?',
  };

  return welcomes[category] || `Welcome! Let's get you started.`;
}

Campaign Context

Users from marketing campaigns expect to see what was advertised:

function CampaignOnboarding({ intent }) {
  const campaign = getCampaignConfig(intent.campaign);

  return (
    <View>
      <CampaignLanding
        headline={campaign.headline}
        heroImage={campaign.image}
        ctaText={campaign.cta}
      />

      <AccountCreation promoCode={campaign.promoCode} />

      {/* Navigate to the campaign-specific content */}
      <Redirect to={campaign.destinationScreen} />
    </View>
  );
}

function getCampaignConfig(campaignId) {
  const campaigns = {
    summer_sale: {
      headline: 'Summer Sale: Up to 50% Off',
      image: 'summer-sale-hero.jpg',
      cta: 'Shop the Sale',
      promoCode: 'SUMMER50',
      destinationScreen: '/sale/summer',
    },
    new_feature: {
      headline: 'Introducing Workout Tracking',
      image: 'workout-tracking-hero.jpg',
      cta: 'Try It Free',
      promoCode: null,
      destinationScreen: '/feature/workout-tracking',
    },
  };

  return campaigns[campaignId] || { headline: 'Welcome', cta: 'Get Started' };
}

Context Confidence Levels

Not all context is equally reliable. Handle uncertainty:

High Confidence (Act on It)

  • Specific product ID in the URL
  • Referrer ID with valid account
  • Known campaign with active config

These are safe to use for onboarding customization. Show the product, acknowledge the referrer, display the campaign offer.

Medium Confidence (Suggest, Don't Assume)

  • Category from UTM parameters
  • Feature interest from content link
  • Location from QR code

Use these to pre-select options or reorder content, but let the user change. For a reference on which parameters to include in your links, see Onboarding Deep Link Parameters.

function InterestPicker({ suggestedCategory }) {
  const [selected, setSelected] = useState(suggestedCategory);

  return (
    <View>
      {suggestedCategory && (
        <Text>Based on how you found us, we think you're interested in:</Text>
      )}

      <CategoryGrid
        categories={allCategories}
        selected={selected}
        onSelect={setSelected}
        highlighted={suggestedCategory}
      />
    </View>
  );
}

Low Confidence (Fall Back to Default)

  • No deep link data (organic install)
  • Deep link with only UTM source (no specific content)
  • Expired or invalid deep link

Use the standard onboarding flow.

Contextual Permission Requests

Tie permission requests to the user's intent:

function getPermissionContext(intent) {
  switch (intent.type) {
    case 'product_specific':
      return {
        push: 'Get notified when this item goes on sale or ships.',
        location: 'Find stores near you that carry this item.',
      };

    case 'category_interest':
      return {
        push: `Get alerts for new ${intent.category} arrivals and deals.`,
        location: null, // Not relevant
      };

    case 'referral':
      return {
        push: `Get notified when ${intent.referrerName} shares something new.`,
        location: null,
      };

    default:
      return {
        push: 'Get notified about updates and personalized recommendations.',
        location: 'Find relevant content near you.',
      };
  }
}

Contextual permission explanations have higher grant rates because the user understands the specific benefit.

Handling Context Across Sessions

Persisting Context

Store the intent data so it can influence the experience beyond the first session:

async function persistIntent(userId, intent) {
  await userPreferences.set(userId, {
    initialIntent: intent,
    primaryCategory: intent.category,
    acquisitionSource: intent.source,
    referrer: intent.referrer,
    capturedAt: Date.now(),
  });
}

Using Context After Onboarding

The deep link context is valuable beyond onboarding:

  • Home feed: Prioritize content from the user's initial category
  • Recommendations: Weight suggestions toward the initial interest
  • Notifications: Reference the initial context ("More items like the one you first looked at")
  • Re-engagement: If the user churns, remind them of their original interest

Measuring Contextual Onboarding

Compare Against Standard

async function contextualOnboardingReport(dateRange) {
  const segments = [
    { name: 'Organic (no context)', filter: { intentType: 'organic' } },
    { name: 'Product-specific', filter: { intentType: 'product_specific' } },
    { name: 'Category interest', filter: { intentType: 'category_interest' } },
    { name: 'Referral', filter: { intentType: 'referral' } },
    { name: 'Campaign', filter: { intentType: 'campaign' } },
  ];

  for (const seg of segments) {
    const completion = await getCompletionRate(dateRange, seg.filter);
    const activation = await getActivationRate(dateRange, seg.filter);
    const retention = await getDay7Retention(dateRange, seg.filter);

    console.log(seg.name, {
      completion: completion.toFixed(1) + '%',
      activation: activation.toFixed(1) + '%',
      day7Retention: retention.toFixed(1) + '%',
    });
  }
}

Expected Results

Segment Completion Activation Day 7 Retention
Organic 42% 18% 12%
Product-specific 58% 35% 22%
Category interest 52% 28% 18%
Referral 68% 42% 30%
Campaign 48% 22% 14%

Product-specific and referral contexts produce the highest-quality users because the intent is clearest.

For deferred deep linking, see the deferred deep linking docs. For deep linking features, see Tolinku deep linking. For onboarding use cases, see the onboarding documentation.

Get deep linking tips in your inbox

One email per week. No spam.

Ready to add deep linking to your app?

Set up Universal Links, App Links, deferred deep linking, and analytics in minutes. Free to start.