From 20a4123dfce737fd71be84d9c4fb407cd8f80550 Mon Sep 17 00:00:00 2001 From: Ian MacCallum Date: Tue, 23 Sep 2025 10:04:15 -0400 Subject: [PATCH] Adds UIKit / RN docs and code samples --- concepts/deep-links/attribution.mdx | 197 +++++++++++++++++- concepts/deep-links/quickstart.mdx | 130 ++++++++++-- docs.json | 4 +- .../installation-guides/react-native.mdx | 40 ++++ .../installation-guides/swift.mdx | 15 +- sdks/client-side-mobile/introduction.mdx | 22 +- ...install.mdx => dub-client-ios-install.mdx} | 165 ++++++++++++++- .../dub-client-mobile-installation-guides.mdx | 8 +- snippets/dub-client-react-native-install.mdx | 171 +++++++++++++++ snippets/steps/initialize-ios-sdk.mdx | 22 ++ .../steps/initialize-react-native-sdk.mdx | 39 ++++ snippets/steps/install-react-native-sdk.mdx | 14 ++ 12 files changed, 805 insertions(+), 22 deletions(-) create mode 100644 sdks/client-side-mobile/installation-guides/react-native.mdx rename snippets/{dub-client-mobile-install.mdx => dub-client-ios-install.mdx} (54%) create mode 100644 snippets/dub-client-react-native-install.mdx create mode 100644 snippets/steps/initialize-react-native-sdk.mdx create mode 100644 snippets/steps/install-react-native-sdk.mdx diff --git a/concepts/deep-links/attribution.mdx b/concepts/deep-links/attribution.mdx index 027faac2..35ea85df 100644 --- a/concepts/deep-links/attribution.mdx +++ b/concepts/deep-links/attribution.mdx @@ -7,9 +7,11 @@ description: "Learn how to use deep link attribution to track conversions events import EnableConversionTracking from "/snippets/enable-conversion-tracking.mdx"; import GeneratePublishableKeyStep from "/snippets/steps/generate-publishable-key.mdx"; import AllowlistDomainsStep from "/snippets/steps/allowlist-domains.mdx"; -import InstallationGuides from "/snippets/dub-client-mobile-installation-guides.mdx"; +import InstallationGuides from "/snippets/dub-client-ios-installation-guides.mdx"; import InstallIosSdkStep from "/snippets/steps/install-ios-sdk.mdx"; +import InstallReactNativeSdkStep from "/snippets/steps/install-react-native-sdk.mdx"; import InitializeIosSdkStep from "/snippets/steps/initialize-ios-sdk.mdx"; +import InitializeReactNativeSdkStep from "/snippets/steps/initialize-react-native-sdk.mdx"; import ViewConversions from "/snippets/view-conversions.mdx"; @@ -52,7 +54,19 @@ Once these are set up, we can start tracking conversion events for your deep lin ## Step 1: Install the client-side Mobile SDK - + + +Install the [Dub React Native SDK](/sdks/client-side-mobile/installation-guides/react-native) and initialize it with your publishable key and short link domain. + + + + + + + + + + Install the [Dub iOS SDK](/sdks/client-side-mobile/installation-guides/swift) and initialize it with your publishable key and short link domain. @@ -74,6 +88,60 @@ Call `trackOpen` on the `dub` instance to track deep link and deferred deep link +```typescript React Native expandable +import { useState, useEffect, useRef } from "react"; +import { Linking } from "react-native"; +import AsyncStorage from "@react-native-async-storage/async-storage"; +import dub from "@dub/react-native"; + +export default function App() { + useEffect(() => { + dub.init({ + publishableKey: "", + domain: "", + }); + + // Check if this is first launch + const isFirstLaunch = await AsyncStorage.getItem("is_first_launch"); + + if (isFirstLaunch === null) { + await handleFirstLaunch(); + await AsyncStorage.setItem("is_first_launch", "false"); + } else { + // Handle initial deep link url (Android only) + const url = await Linking.getInitialURL(); + + if (url) { + await handleDeepLink(url); + } + } + + const linkingListener = Linking.addEventListener("url", (event) => { + handleDeepLink(event.url); + }); + + return () => { + linkingListener.remove(); + }; + }, []); + + const handleFirstLaunch = async ( + deepLinkUrl?: string | null | undefined + ): Promise => { + try { + const response = await dub.trackOpen(deepLinkUrl); + + const destinationURL = response.link?.url; + // Navigate to the destination URL + } catch (error) { + // Handle error + } + }; + + // Return your app... +} +``` + ```swift iOS (SwiftUI) expandable // ContentView.swift import SwiftUI @@ -121,6 +189,71 @@ struct ContentView: View { } ``` +```swift iOS (UIKit) expandable +import UIKit +import Dub + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + private let dubPublishableKey = "" + private let dubDomain = "" + + private var isFirstLaunch: Bool { + get { + UserDefaults.standard.object(forKey: "is_first_launch") as? Bool ?? true + } + set { + UserDefaults.standard.set(newValue, forKey: "is_first_launch") + } + } + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + Dub.setup(publishableKey: dubPublishableKey, domain: dubDomain) + + // Track first launch + if isFirstLaunch { + trackOpen() + isFirstLaunch = false + } + + // Override point for customization after application launch. + return true + } + + func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { + handleDeepLink(url: url) + return true + } + + func handleDeepLink(url: URL) { + trackOpen(deepLink: url) + } + + private func trackOpen(deepLink: URL? = nil) { + // Call the tracking endpoint with the full deep link URL + Task { + do { + let response = try await Dub.shared.trackOpen(deepLink: deepLink) + + print(response) + + // Navigate to final link via link.url + guard let destinationUrl = response.link?.url else { + return + } + + // Navigate to the destination URL + } catch let error as DubError { + print(error.localizedDescription) + } + } + } +} +``` + If the deep link was successfully resolved and correlated to the original click, the `response` object will contain the destination URL, which you can use to navigate the user to the appropriate screen. @@ -133,6 +266,36 @@ You may track conversion events directly in your app with the `trackLead` and `t +```typescript React Native expandable +import dub from "@dub/react-native"; + +function trackLead(user: User) { + try { + await dub.trackLead({ + eventName: "User Sign Up", + customerExternalId: user.id, + customerName: user.name, + customerEmail: user.email, + }); + } catch (error) { + // Handle sale tracking error + } +} + +function trackSale(user: User, product: Product) { + try { + await dub.trackSale({ + customerExternalId: user.id, + amount: product.price.amount, + currency: "usd", + eventName: "Purchase", + }); + } catch (error) { + // Handle sale tracking error + } +} +``` + ```swift iOS (SwiftUI) expandable // ContentView.swift import SwiftUI @@ -193,6 +356,36 @@ struct ContentView: View { } ``` +```swift iOS (UIKit) expandable +// ViewController.swift +import UIKit +import Dub + +class ViewController: UIViewController { + // View controller lifecycle + + private func trackLead(customerExternalId: String, name: String, email: String) { + Task { + do { + let response = try await dub.trackLead(customerExternalId: customerExternalId, name: name, email: email) + } catch let error as DubError { + print(error.localizedDescription) + } + } + } + + private func trackSale(customerExternalId: String, amount: Int, currency: String = "usd", eventName: String? = "Purchase", customerName: String? = nil, customerEmail: String? = nil, customerAvatar: String? = nil) { + Task { + do { + let response = try await dub.trackSale(customerExternalId: customerExternalId, amount: amount, currency: currency, eventName: eventName, customerName: customerName, customerEmail: customerEmail, customerAvatar: customerAvatar) + } catch let error as DubError { + print(error.localizedDescription) + } + } + } +} +``` + Alternatively, you can [track conversion events server-side](/conversions/quickstart#step-3%3A-install-the-dub-server-side-sdk-%2B-track-conversion-events) for [lead events](/conversions/leads/introduction) and [sale events](/conversions/sales/introduction) by sending the `clickId` resolved from the deep link to your backend and then calling off to either: diff --git a/concepts/deep-links/quickstart.mdx b/concepts/deep-links/quickstart.mdx index 3e8efad7..93072b27 100644 --- a/concepts/deep-links/quickstart.mdx +++ b/concepts/deep-links/quickstart.mdx @@ -189,13 +189,67 @@ When a user opens your app from a deep link, you need to handle two main scenari When your app is already installed, the deep link will open your app directly. You may handle the deep link manually or with the supported mobile SDKs. -**Option 1**: Handle the deep link using a supported [Dub Mobile SDK](/sdks/client-side-mobile/introduction) (iOS only) +**Option 1**: Handle the deep link using a supported [Dub Mobile SDK](/sdks/client-side-mobile/introduction) (iOS & React Native only) -Follow our [Swift Installation Guide](/sdks/client-side-mobile/installation-guides/swift) to get started. +Follow our installation guide for [Swift](/sdks/client-side-mobile/installation-guides/swift) or [React Native](/sdks/client-side-mobile/installation-guides/react-native) to get started. -```swift iOS (SwiftUI) +```typescript React Native expandable +import { useState, useEffect, useRef } from "react"; +import { Linking } from "react-native"; +import AsyncStorage from "@react-native-async-storage/async-storage"; +import dub from "@dub/react-native"; + +export default function App() { + useEffect(() => { + dub.init({ + publishableKey: "", + domain: "", + }); + + // Check if this is first launch + const isFirstLaunch = await AsyncStorage.getItem("is_first_launch"); + + if (isFirstLaunch === null) { + await handleFirstLaunch(); + await AsyncStorage.setItem("is_first_launch", "false"); + } else { + // Handle initial deep link url (Android only) + const url = await Linking.getInitialURL(); + + if (url) { + await handleDeepLink(url); + } + } + + const linkingListener = Linking.addEventListener("url", (event) => { + handleDeepLink(event.url); + }); + + return () => { + linkingListener.remove(); + }; + }, []); + + const handleFirstLaunch = async ( + deepLinkUrl?: string | null | undefined + ): Promise => { + try { + const response = await dub.trackOpen(deepLinkUrl); + + const destinationURL = response.link?.url; + // Navigate to the destination URL + } catch (error) { + // Handle error + } + }; + + // Return your app... +} +``` + +```swift iOS (SwiftUI) expandable // ContentView.swift import SwiftUI import Dub @@ -242,16 +296,68 @@ struct ContentView: View { } ``` -```swift iOS (UIKit) -// AppDelegate.swift -func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { - handleDeepLink(url: url) - return true -} +```swift iOS (UIKit) expandable +import UIKit +import Dub -func handleDeepLink(url: URL) { - // Call the tracking endpoint with the full deep link URL - trackDeepLinkClick(deepLink: url.absoluteString) +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + private let dubPublishableKey = "" + private let dubDomain = "" + + private var isFirstLaunch: Bool { + get { + UserDefaults.standard.object(forKey: "is_first_launch") as? Bool ?? true + } + set { + UserDefaults.standard.set(newValue, forKey: "is_first_launch") + } + } + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + Dub.setup(publishableKey: dubPublishableKey, domain: dubDomain) + + // Track first launch + if isFirstLaunch { + trackOpen() + isFirstLaunch = false + } + + // Override point for customization after application launch. + return true + } + + func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { + handleDeepLink(url: url) + return true + } + + func handleDeepLink(url: URL) { + trackOpen(deepLink: url) + } + + private func trackOpen(deepLink: URL? = nil) { + // Call the tracking endpoint with the full deep link URL + Task { + do { + let response = try await Dub.shared.trackOpen(deepLink: deepLink) + + print(response) + + // Navigate to final link via link.url + guard let destinationUrl = response.link?.url else { + return + } + + // Navigate to the destination URL + } catch let error as DubError { + print(error.localizedDescription) + } + } + } } ``` diff --git a/docs.json b/docs.json index 57c7938d..4b4e5322 100644 --- a/docs.json +++ b/docs.json @@ -176,12 +176,14 @@ }, { "group": "Client-side SDK (Mobile)", + "tag": "Beta", "pages": [ "sdks/client-side-mobile/introduction", { "group": "Installation Guides", "pages": [ - "sdks/client-side-mobile/installation-guides/swift" + "sdks/client-side-mobile/installation-guides/swift", + "sdks/client-side-mobile/installation-guides/react-native" ] } ] diff --git a/sdks/client-side-mobile/installation-guides/react-native.mdx b/sdks/client-side-mobile/installation-guides/react-native.mdx new file mode 100644 index 00000000..2a1a2aba --- /dev/null +++ b/sdks/client-side-mobile/installation-guides/react-native.mdx @@ -0,0 +1,40 @@ +--- +title: React Native +description: How to add the Dub React Native SDK to your React Native project +tag: "Beta" +--- + +import DubReactNativeInstall from "/snippets/dub-client-react-native-install.mdx"; +import DubAnalyticsParams from "/snippets/dub-analytics-params-react.mdx"; +import DubClientInstallVerify from "/snippets/dub-client-install-verify.mdx"; + +## Prerequisites + +Before you get started, make sure you have the following: + +1. Obtain your [publishable key](/api-reference/publishable-keys) (`DUB_PUBLISHABLE_KEY`) from + your [workspace's Analytics settings page](https://app.dub.co/settings/analytics) and select + your domain (`DUB_DOMAIN`) from your [workspace's Custom Domains settings page](https://app.dub.co/links/domains). + +2. (Optional) If you plan to track conversions, follow the [Dub Conversions quickstart guide](/conversions/quickstart) to [enable conversion tracking for your links](/conversions/quickstart#step-1%3A-enable-conversion-tracking-for-your-links). + +## Quickstart + +This quick start guide will show you how to get started with Dub React Native SDK in your React Native app. + + + +## Examples + +Here are some open-source code examples that you can reference: + + + + See the full example on GitHub. + + diff --git a/sdks/client-side-mobile/installation-guides/swift.mdx b/sdks/client-side-mobile/installation-guides/swift.mdx index b475a8ef..5bdb354f 100644 --- a/sdks/client-side-mobile/installation-guides/swift.mdx +++ b/sdks/client-side-mobile/installation-guides/swift.mdx @@ -1,9 +1,10 @@ --- title: Swift description: How to add the Dub iOS SDK to your Swift project +tag: "Beta" --- -import DubSwiftInstall from "/snippets/dub-client-mobile-install.mdx"; +import DubSwiftInstall from "/snippets/dub-client-ios-install.mdx"; import DubAnalyticsParams from "/snippets/dub-analytics-params-react.mdx"; import DubClientInstallVerify from "/snippets/dub-client-install-verify.mdx"; @@ -11,7 +12,9 @@ import DubClientInstallVerify from "/snippets/dub-client-install-verify.mdx"; Before you get started, make sure you have the following: -1. Obtain your [publishable key](/api-reference/publishable-keys) (`DUB_PUBLISHABLE_KEY`) from your [workspace's Analytics settings page](https://app.dub.co/settings/analytics) and allowlist your site's domain (`DUB_DOMAIN`) to allow the client-side conversion events to be ingested by Dub. +1. Obtain your [publishable key](/api-reference/publishable-keys) (`DUB_PUBLISHABLE_KEY`) from + your [workspace's Analytics settings page](https://app.dub.co/settings/analytics) and select + your domain (`DUB_DOMAIN`) from your [workspace's Custom Domains settings page](https://app.dub.co/links/domains). 2. (Optional) If you plan to track conversions, follow the [Dub Conversions quickstart guide](/conversions/quickstart) to [enable conversion tracking for your links](/conversions/quickstart#step-1%3A-enable-conversion-tracking-for-your-links). @@ -34,4 +37,12 @@ Here are some open-source code examples that you can reference: > See the full example on GitHub. + + See the full example on GitHub. + diff --git a/sdks/client-side-mobile/introduction.mdx b/sdks/client-side-mobile/introduction.mdx index 724c578c..1b49bb9c 100644 --- a/sdks/client-side-mobile/introduction.mdx +++ b/sdks/client-side-mobile/introduction.mdx @@ -10,14 +10,14 @@ Dub offers first-party, open-source, mobile SDKs to help you track [deep links]( Currently, we support the following mobile SDKs: -- [Dub iOS SDK](https://github.com/dubinc/dub-ios) +- [Dub iOS SDK (beta)](https://github.com/dubinc/dub-ios) +- [Dub React Native SDK (beta)](https://github.com/dubinc/dub-react-native) - React Native and Android support are coming soon. If you'd like early access, please [contact + Android support is coming soon. If you'd like early access, please [contact us](https://dub.co/contact/support). - ## Installation guides Dub currently supports the following client-side mobile SDKs: @@ -37,4 +37,20 @@ Here are some open-source code examples that you can reference: > See the full example on GitHub. + + See the full example on GitHub. + + + See the full example on GitHub. + diff --git a/snippets/dub-client-mobile-install.mdx b/snippets/dub-client-ios-install.mdx similarity index 54% rename from snippets/dub-client-mobile-install.mdx rename to snippets/dub-client-ios-install.mdx index c6b44bad..46841191 100644 --- a/snippets/dub-client-mobile-install.mdx +++ b/snippets/dub-client-ios-install.mdx @@ -50,6 +50,27 @@ struct DubApp: App { } } } +``` + +```swift iOS (UIKit) +import UIKit +import Dub + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + // Step 1: Obtain your Dub domain and publishable key + private let dubPublishableKey = "" + private let dubDomain = "" + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Step 2: Initialize the Dub SDK by calling `setup` + Dub.setup(publishableKey: dubPublishableKey, domain: dubDomain) + return true + } +} ``` @@ -110,6 +131,71 @@ struct ContentView: View { } ``` +```swift iOS (UIKit) expandable +import UIKit +import Dub + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + private let dubPublishableKey = "" + private let dubDomain = "" + + private var isFirstLaunch: Bool { + get { + UserDefaults.standard.object(forKey: "is_first_launch") as? Bool ?? true + } + set { + UserDefaults.standard.set(newValue, forKey: "is_first_launch") + } + } + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + Dub.setup(publishableKey: dubPublishableKey, domain: dubDomain) + + // Track first launch + if isFirstLaunch { + trackOpen() + isFirstLaunch = false + } + + // Override point for customization after application launch. + return true + } + + func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { + handleDeepLink(url: url) + return true + } + + func handleDeepLink(url: URL) { + trackOpen(deepLink: url) + } + + private func trackOpen(deepLink: URL? = nil) { + // Call the tracking endpoint with the full deep link URL + Task { + do { + let response = try await Dub.shared.trackOpen(deepLink: deepLink) + + print(response) + + // Navigate to final link via link.url + guard let destinationUrl = response.link?.url else { + return + } + + // Navigate to the destination URL + } catch let error as DubError { + print(error.localizedDescription) + } + } + } +} +``` + @@ -152,6 +238,33 @@ struct ContentView: View { } ``` +```swift iOS (UIKit) expandable +// ViewController.swift +import UIKit +import Dub + +class ViewController: UIViewController { + // View controller lifecycle... + + private func trackLead(customerExternalId: String, name: String, email: String) { + Task { + do { + let response = try await Dub.shared.trackLead( + eventName: "User Sign Up", + customerExternalId: customerExternalId, + customerName: name, + customerEmail: email + ) + + print(response) + } catch let error as DubError { + print(error.localizedDescription) + } + } + } +} +``` + @@ -162,7 +275,9 @@ struct ContentView: View { - To track sale events, call `trackSale` on the `dub` instance with your customer's user ID and purchase information. +To track sale events, call `trackSale` on the `dub` instance with your customer's user ID and purchase information. + + ```swift iOS (SwiftUI) expandable // ContentView.swift @@ -215,6 +330,54 @@ struct ContentView: View { } ``` +```swift iOS (UIKit) expandable +// ViewController.swift +import UIKit +import Dub + +class ViewController: UIViewController { + // View controller lifecycle... + + private func trackSale( + customerExternalId: String, + amount: Int, + currency: String = "usd", + eventName: String? = "Purchase", + paymentProcessor: PaymentProcessor = .custom, + invoiceId: String? = nil, + metadata: Metadata? = nil, + leadEventName: String? = nil, + customerName: String? = nil, + customerEmail: String? = nil, + customerAvatar: String? = nil + ) { + Task { + do { + let response = try await Dub.shared.trackSale( + customerExternalId: customerExternalId, + amount: amount, + currency: currency, + eventName: eventName, + paymentProcessor: paymentProcessor, + invoiceId: invoiceId, + metadata: metadata, + leadEventName: leadEventName, + customerName: customerName, + customerEmail: customerEmail, + customerAvatar: customerAvatar + ) + + print(response) + } catch let error as DubError { + print(error.localizedDescription) + } + } + } +} +``` + + + diff --git a/snippets/dub-client-mobile-installation-guides.mdx b/snippets/dub-client-mobile-installation-guides.mdx index 8510021d..44a99d79 100644 --- a/snippets/dub-client-mobile-installation-guides.mdx +++ b/snippets/dub-client-mobile-installation-guides.mdx @@ -1,4 +1,3 @@ - Add the Dub iOS SDK to your app (Swift) + + Add the Dub React Native SDK to your app (React Native) + diff --git a/snippets/dub-client-react-native-install.mdx b/snippets/dub-client-react-native-install.mdx new file mode 100644 index 00000000..fa231cab --- /dev/null +++ b/snippets/dub-client-react-native-install.mdx @@ -0,0 +1,171 @@ +import LeadAttributes from "/snippets/lead-attributes.mdx"; +import SaleAttributes from "/snippets/sale-attributes.mdx"; + + + + +```sh +# With npm +npm install @dub/react-native + +# With yarn +yarn add @dub/react-native + +# With pnpm +pnpm add @dub/react-native +``` + + + + + +You must call `init` on your `dub` instance with your publishable key and domain prior to being able to use the `dub` instance. We provide two ways to initialize the SDK: + +**Option 1**: Use the `DubProvider` to wrap your app + +```typescript +import { DubProvider } from "@dub/react-native"; + +export default function App() { + return ( + + // Your app content... + + ); +} +``` + +**Option 2**: Manually initialize the Dub SDK + +```typescript +import dub from "@dub/react-native"; + +export default function App() { + useEffect(() => { + dub.init({ + publishableKey: "", + domain: "", + }); + }, []); + + // Return your app... +} +``` + + + + +Call `trackOpen` on the `dub` instance to track deep link and deferred deep link open events. +The `trackOpen` function should be called once without a `deepLink` parameter on first launch, and then +again with the `deepLink` parameter whenever the app is opened from a deep link. + +```typescript React Native expandable +import { useState, useEffect, useRef } from "react"; +import { Linking } from "react-native"; +import AsyncStorage from "@react-native-async-storage/async-storage"; +import dub from "@dub/react-native"; + +export default function App() { + useEffect(() => { + dub.init({ + publishableKey: "", + domain: "", + }); + + // Check if this is first launch + const isFirstLaunch = await AsyncStorage.getItem("is_first_launch"); + + if (isFirstLaunch === null) { + await handleFirstLaunch(); + await AsyncStorage.setItem("is_first_launch", "false"); + } else { + // Handle initial deep link url (Android only) + const url = await Linking.getInitialURL(); + + if (url) { + await handleDeepLink(url); + } + } + + const linkingListener = Linking.addEventListener("url", (event) => { + handleDeepLink(event.url); + }); + + return () => { + linkingListener.remove(); + }; + }, []); + + const handleFirstLaunch = async ( + deepLinkUrl?: string | null | undefined + ): Promise => { + try { + const response = await dub.trackOpen(deepLinkUrl); + + const destinationURL = response.link?.url; + // Navigate to the destination URL + } catch (error) { + // Handle error + } + }; + + // Return your app... +} +``` + + + + + +To track lead events, call `trackLead` on the `dub` instance with your customer's external ID, name, and email. + +```typescript React Native +import dub from "@dub/react-native"; + +try { + await dub.trackLead({ + eventName: "User Sign Up", + customerExternalId: user.id, + customerName: user.name, + customerEmail: user.email, + }); +} catch (error) { + // Handle sale tracking error +} +``` + + + + + + + + + +To track sale events, call `trackSale` on the `dub` instance with your customer's user ID and purchase information. + +```typescript React Native +import dub from "@dub/react-native"; + +try { + await dub.trackSale({ + customerExternalId: user.id, + amount: product.price.amount, + currency: "usd", + eventName: "Purchase", + }); +} catch (error) { + // Handle sale tracking error +} +``` + + + + + + + + diff --git a/snippets/steps/initialize-ios-sdk.mdx b/snippets/steps/initialize-ios-sdk.mdx index 2b93f0b4..129502bc 100644 --- a/snippets/steps/initialize-ios-sdk.mdx +++ b/snippets/steps/initialize-ios-sdk.mdx @@ -26,4 +26,26 @@ struct DubApp: App { } } ``` + +```swift iOS (UIKit) +import UIKit +import Dub + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + + var window: UIWindow? + + // Step 1: Obtain your Dub domain and publishable key + private let dubPublishableKey = "" + private let dubDomain = "" + + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + // Step 2: Initialize the Dub SDK by calling `setup` + Dub.setup(publishableKey: dubPublishableKey, domain: dubDomain) + return true + } +} +``` + diff --git a/snippets/steps/initialize-react-native-sdk.mdx b/snippets/steps/initialize-react-native-sdk.mdx new file mode 100644 index 00000000..34f47483 --- /dev/null +++ b/snippets/steps/initialize-react-native-sdk.mdx @@ -0,0 +1,39 @@ + + +You must call `init` on your `dub` instance with your publishable key and domain prior to being able to use the `dub` instance. We provide two ways to initialize the SDK: + +**Option 1**: Use the `DubProvider` to wrap your app + +```typescript +import { DubProvider } from "@dub/react-native"; + +export default function App() { + return ( + + // Your app content... + + ); +} +``` + +**Option 2**: Manually initialize the Dub SDK + +```typescript +import dub from "@dub/react-native"; + +export default function App() { + useEffect(() => { + dub.init({ + publishableKey: "", + domain: "", + }); + }, []); + + // Return your app... +} +``` + + diff --git a/snippets/steps/install-react-native-sdk.mdx b/snippets/steps/install-react-native-sdk.mdx new file mode 100644 index 00000000..1b30531f --- /dev/null +++ b/snippets/steps/install-react-native-sdk.mdx @@ -0,0 +1,14 @@ + + +```sh +# With npm +npm install @dub/react-native + +# With yarn +yarn add @dub/react-native + +# With pnpm +pnpm add @dub/react-native +``` + +