RiftRift

Deep Linking

Create Links

Create deep links with per-platform destinations and metadata for rich social previews.

Create a link

The CLI walks you through link creation interactively, or you can pass flags directly:

# Interactive — prompts for each field
rift links create

# Non-interactive — pass flags directly
rift links create \
  --web-url https://example.com/promo/summer-sale \
  --ios-deep-link myapp://promo/summer-sale \
  --android-deep-link myapp://promo/summer-sale \
  --custom-id summer-sale

The CLI outputs the link ID and URL, and suggests rift links test to preview how it resolves across platforms:

rift links test summer-sale
Important: Custom IDs (vanity slugs like summer-sale) require a verified custom domain. They are unique per tenant — different tenants can use the same slug on their own domains (e.g. go.acme.com/summer-sale and go.brand.com/summer-sale). Links with custom IDs resolve via your custom domain, not the primary riftl.ink/r/ path.

If you omit custom_id, Rift auto-generates a short ID (e.g. A1B2C3D4). Auto-generated links work for all tenants and resolve via riftl.ink/r/A1B2C3D4 — no custom domain required.

2

How resolution works

When a user clicks the link, Rift detects their platform and serves a smart landing page that:

  • iOS — attempts to open the deep link, falls back to the App Store
  • Android — attempts to open the deep link, falls back to the Play Store
  • Desktop — redirects to the web URL

The landing page includes your app branding (from app registration) and OG tags from link metadata for rich social previews.

3

JSON resolution for agents

Agents sending Accept: application/json receive all destinations and metadata as JSON. Use your custom domain for custom IDs:

# Custom ID via custom domain
curl https://go.yourcompany.com/summer-sale \
  -H "Accept: application/json"

# Auto-generated ID via primary domain
curl https://api.riftl.ink/r/A1B2C3D4 \
  -H "Accept: application/json"

{
  "link_id": "summer-sale",
  "ios_deep_link": "myapp://promo/summer-sale",
  "android_deep_link": "myapp://promo/summer-sale",
  "web_url": "https://example.com/promo/summer-sale",
  "ios_store_url": "https://apps.apple.com/app/id123456789",
  "android_store_url": "https://play.google.com/store/apps/details?id=com.example.myapp",
  "metadata": { "title": "Summer Sale — 50% Off", "description": "..." },
  "agent_context": {
    "action": "purchase",
    "cta": "Get 50% Off",
    "description": "Summer clearance sale on all products with free shipping"
  },
  "_rift_meta": {
    "context": "This is a Rift deep link...",
    "source": "tenant_asserted",
    "status": "active",
    "tenant_domain": "go.yourcompany.com",
    "tenant_verified": true
  }
}

Handle incoming links

4

iOS — SceneDelegate or AppDelegate

// SceneDelegate.swift
func scene(_ scene: UIScene,
           continue userActivity: NSUserActivity) {
    guard userActivity.activityType ==
              NSUserActivityTypeBrowsingWeb,
          let url = userActivity.webpageURL else { return }

    let linkId = url.path
        .trimmingCharacters(in: CharacterSet(charactersIn: "/"))
    handleDeepLink(linkId: linkId)
}
5

Android — Intent handling

// MainActivity.kt
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    intent?.data?.let { uri ->
        val linkId = uri.path?.trimStart('/')
        if (linkId != null) handleDeepLink(linkId)
    }
}