diff --git a/api-reference/introduction.mdx b/api-reference/introduction.mdx
index e81450aa..9e773e93 100644
--- a/api-reference/introduction.mdx
+++ b/api-reference/introduction.mdx
@@ -16,7 +16,7 @@ https://api.dub.co
## Authentication
-Authentication to Dub's API is performed via the Authorization header with a Bearer token. To authenticate, you need to include the Authorization header with the word `Bearer` followed by your API key in your requests like so:
+Authentication to Dub's API is performed via the Authorization header with a Bearer token. To authenticate, you need to include the Authorization header with the word `Bearer` followed by your [API key](/api-reference/tokens) in your requests like so:
```bash Terminal
Authorization: Bearer dub_xxxxxx
diff --git a/api-reference/publishable-keys.mdx b/api-reference/publishable-keys.mdx
new file mode 100644
index 00000000..48ee173c
--- /dev/null
+++ b/api-reference/publishable-keys.mdx
@@ -0,0 +1,32 @@
+---
+title: "Publishable keys"
+description: "Learn how publishable keys work on Dub."
+---
+
+import GeneratePublishableKeyStep from "/snippets/steps/generate-publishable-key.mdx";
+import AllowlistDomainsStep from "/snippets/steps/allowlist-domains.mdx";
+
+Publishable keys on Dub allow you to safely embed authentication in client-side applications.
+These keys are specifically designed to be used with [Dub's client-side SDKs](/sdks/client-side/introduction) for features like [conversion tracking](/sdks/client-side/features/conversion-tracking).
+
+Unlike [API keys](/api-reference/tokens) which must be kept secret, publishable keys can be safely exposed in your frontend code since they have limited capabilities.
+
+Publishable keys on Dub follow the format:
+
+```bash .env
+DUB_PUBLISHABLE_KEY=dub_pk_xxxxxxxxxxxxxxxxxxxxxxxx
+```
+
+## Create a publishable key
+
+You can create a publishable key by following these steps:
+
+
+
+
+
+
+
+You can now use your publishable key to authenticate client-side requests in your application. Usage will depend on the client-side SDK you are using.
+
+
diff --git a/concepts/deep-links/attribution.mdx b/concepts/deep-links/attribution.mdx
index e3b39e5c..027faac2 100644
--- a/concepts/deep-links/attribution.mdx
+++ b/concepts/deep-links/attribution.mdx
@@ -4,9 +4,204 @@ og:title: "How to set up deep link attribution with Dub"
description: "Learn how to use deep link attribution to track conversions events with Dub."
---
+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 InstallIosSdkStep from "/snippets/steps/install-ios-sdk.mdx";
+import InitializeIosSdkStep from "/snippets/steps/initialize-ios-sdk.mdx";
+import ViewConversions from "/snippets/view-conversions.mdx";
+
- This feature is coming soon. If you'd like early access, please [contact
+ Deep link attribution requires a [Business plan](https://dub.co/pricing)
+ subscription or higher.
+
+
+Dub's powerful [attribution platform](https://dub.co/analytics) lets you understand how well your deep links are translating to actual users and revenue dollars inside your app.
+
+
+
+
+
+
+ This feature is currently only available for iOS (Swift). React Native and
+ Android support are coming soon. If you'd like early access, please [contact
us](https://dub.co/contact/support).
-With [Dub Conversions](/conversions/quickstart), you can easily track conversion events from your deep links.
+## Prerequisites
+
+
+
+Then, you'll need generate a [publishable key](/api-reference/publishable-keys) from your Dub workspace to track conversions on the client-side.
+
+To do that, navigate to your [workspace's Analytics settings page](https://app.dub.co/settings/analytics) and generate a new publishable key under the **Publishable Key** section.
+
+
+
+
+
+Once these are set up, we can start tracking conversion events for your deep links.
+
+## Step 1: Install the client-side Mobile SDK
+
+
+
+
+Install the [Dub iOS SDK](/sdks/client-side-mobile/installation-guides/swift) and initialize it with your publishable key and short link domain.
+
+
+
+
+
+
+
+
+
+
+
+## Step 2: Track deep link open events
+
+Once the SDK has been initialized, you can start tracking deep link and deferred deep link events.
+
+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.
+
+
+
+```swift iOS (SwiftUI) expandable
+// ContentView.swift
+import SwiftUI
+import Dub
+
+struct ContentView: View {
+
+ @Environment(\.dub) var dub: Dub
+
+ @AppStorage("is_first_launch") private var isFirstLaunch = true
+
+ var body: some View {
+ NavigationStack {
+ VStack {
+ // Your app content
+ }
+ .onOpenURL { url in
+ trackOpen(deepLink: url)
+ }
+ .onAppear {
+ if isFirstLaunch {
+ trackOpen()
+ isFirstLaunch = false
+ }
+ }
+ }
+ }
+
+ private func trackOpen(deepLink: URL? = nil) {
+ Task {
+ do {
+ let response = try await dub.trackOpen(deepLink: deepLink)
+
+ // Obtain the destination URL from the response
+ guard let url = 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.
+
+It will also contain the `clickId`, which the `dub` instance will persist internally.
+
+## Step 3: Track conversion events
+
+You may track conversion events directly in your app with the `trackLead` and `trackSale` methods.
+
+
+
+```swift iOS (SwiftUI) expandable
+// ContentView.swift
+import SwiftUI
+import Dub
+
+struct ContentView: View {
+
+ @Environment(\.dub) var dub: Dub
+
+ var body: some View {
+ // ... your app content ...
+ }
+
+ private func trackLead(customerExternalId: String, name: String, email: String) {
+ Task {
+ do {
+ let response = try await dub.trackLead(
+ eventName: "Sign Up",
+ customerExternalId: customerExternalId,
+ customerName: name,
+ customerEmail: email
+ )
+
+ print(response)
+ } 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
+ )
+
+ print(response)
+ } 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:
+
+- [`POST /track/lead`](https://dub.co/docs/api-reference/endpoint/track-lead)
+- [`POST /track/sale`](https://dub.co/docs/api-reference/endpoint/track-sale)
+
+## Step 4: View your conversions
+
+Once you've enabled conversion tracking for your links, all your tracked conversions will show up on your [Analytics dashboard](https://app.dub.co/analytics). We provide 3 different views to help you understand your conversions:
+
+
diff --git a/concepts/deep-links/deferred-deep-linking.mdx b/concepts/deep-links/deferred-deep-linking.mdx
index dde1702a..a453dc72 100644
--- a/concepts/deep-links/deferred-deep-linking.mdx
+++ b/concepts/deep-links/deferred-deep-linking.mdx
@@ -469,7 +469,7 @@ Here is how it works in a nutshell:
2. Dub copies the deep link URL to the clipboard.
3. The user is redirected to the App Store to download your app.
4. After installation, your app reads the clipboard to retrieve the deep link.
-5. Your app calls the [`/track/open` endpoint](/api-reference/endpoint/track-open) with the `deepLink` parameter in the request body.
+5. Your app calls the [`/track/open` endpoint](/api-reference/endpoint/track-open) with the `deepLink` parameter in the request body either directly or via a supported [Dub Mobile SDK](/sdks/client-side-mobile/introduction).
6. Dub returns the destination URL, and your app navigates the user to the appropriate screen (see [deep links quickstart](/concepts/deep-links/quickstart) for more details).
#### 2. Probabilistic IP-based tracking
@@ -479,7 +479,7 @@ This method relies on matching the user’s device IP address from the initial c
1. User taps **Get the App without Copying** button on the landing page.
2. The user is redirected directly to the App Store to download your app.
3. Dub has already tracked the click and stored the IP address at the time of deep link click.
-4. After installation, your app calls the [`/track/open` endpoint](/api-reference/endpoint/track-open) with the `dubDomain` parameter in the request body.
+4. After installation, your app calls the [`/track/open` endpoint](/api-reference/endpoint/track-open) with the `dubDomain` parameter in the request body either directly or via a supported [Dub Mobile SDK](/sdks/client-side-mobile/introduction) .
5. Dub matches the user using IP-based tracking and returns the destination URL.
6. If a destination URL is returned, your app navigates the user to the appropriate screen (see [deep links quickstart](/concepts/deep-links/quickstart) for more details).
@@ -488,7 +488,7 @@ This method relies on matching the user’s device IP address from the initial c
The following logic determines whether to use clipboard-based tracking or IP-based tracking:
- **Clipboard-based tracking**: Used when a deep link is found in the clipboard (e.g., `acme.link`). The app sends the `deepLink` parameter in the request body.
-- **IP-based tracking**: Used when no deep link is found in the clipboard. The app sends only the `dubDomain` parameter, allowing Dub to match the user based on their IP address.
+- **IP-based tracking**: Used when no deep link is found in the clipboard or the user declined paste permissions. The app sends only the `dubDomain` parameter, allowing Dub to match the user based on their IP address.
This ensures the most reliable tracking method is chosen automatically.
@@ -555,7 +555,7 @@ async function trackOpen() {
}
```
-```swift iOS expandable
+```swift iOS (SwiftUI) expandable
import SwiftUI
@main
@@ -677,7 +677,7 @@ export default function App() {
}
```
-```swift iOS expandable
+```swift iOS (SwiftUI) expandable
import SwiftUI
struct ContentView: View {
diff --git a/concepts/deep-links/quickstart.mdx b/concepts/deep-links/quickstart.mdx
index bbea1d8b..3e8efad7 100644
--- a/concepts/deep-links/quickstart.mdx
+++ b/concepts/deep-links/quickstart.mdx
@@ -58,7 +58,7 @@ In the domain modal, click on **Show advanced settings**, which will open up the
**iOS (apple-app-site-association)**
-For iOS apps, upload your Apple App Site Association file to enable iOS deep links:
+For iOS apps, upload your [Apple App Site Association file ](https://developer.apple.com/documentation/xcode/supporting-associated-domains#Add-the-associated-domain-file-to-your-website) to enable iOS deep links:
```json apple-app-site-association
{
@@ -66,7 +66,7 @@ For iOS apps, upload your Apple App Site Association file to enable iOS deep lin
"apps": [],
"details": [
{
- "appID": "YOUR_APP_ID",
+ "appID": ".",
"paths": []
}
]
@@ -103,8 +103,8 @@ Once you've set up your deep link configuration files, you can go to their respe
-
-Last but not least, you'll need to whitelist your deep link domain in your apps to allow them to redirect straight into a page within your app.
+
+Last but not least, you'll need to allowlist your deep link domain in your apps to allow them to redirect straight into a page within your app.
**For iOS apps**, you'll need to [allow websites to link to your apps](https://developer.apple.com/documentation/xcode/allowing-apps-and-websites-to-link-to-your-content/).
@@ -186,7 +186,78 @@ When a user opens your app from a deep link, you need to handle two main scenari
### Scenario 1: User has your app installed
-When your app is already installed, the deep link will open your app directly. Here's how to handle it:
+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)
+
+Follow our [Swift Installation Guide](/sdks/client-side-mobile/installation-guides/swift) to get started.
+
+
+
+```swift iOS (SwiftUI)
+// ContentView.swift
+import SwiftUI
+import Dub
+
+struct ContentView: View {
+
+ @Environment(\.dub) var dub: Dub
+
+ @AppStorage("is_first_launch") private var isFirstLaunch = true
+
+ var body: some View {
+ NavigationStack {
+ VStack {
+ // Your app content
+ }
+ .onOpenURL { url in
+ trackOpen(deepLink: url)
+ }
+ .onAppear {
+ if isFirstLaunch {
+ trackOpen()
+ isFirstLaunch = false
+ }
+ }
+ }
+ }
+
+ private func trackOpen(deepLink: URL? = nil) {
+ Task {
+ do {
+ let response = try await dub.trackOpen(deepLink: deepLink)
+
+ // Obtain the destination URL from the response
+ guard let url = response.link?.url else {
+ return
+ }
+
+ // Navigate to the destination URL
+ } catch let error as DubError {
+ print(error.localizedDescription)
+ }
+ }
+ }
+}
+```
+
+```swift iOS (UIKit)
+// AppDelegate.swift
+func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
+ handleDeepLink(url: url)
+ return true
+}
+
+func handleDeepLink(url: URL) {
+ // Call the tracking endpoint with the full deep link URL
+ trackDeepLinkClick(deepLink: url.absoluteString)
+}
+```
+
+
+
+**Option 2**: Handle the deep link manually
@@ -229,7 +300,7 @@ useEffect(() => {
}, []);
```
-```swift iOS
+```swift iOS (UIKit)
// AppDelegate.swift
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
handleDeepLink(url: url)
@@ -242,6 +313,24 @@ func handleDeepLink(url: URL) {
}
```
+```swift iOS (SwiftUI)
+// ContentView.swift
+struct ContentView: View {
+
+ var body: some View {
+ NavigationStack {
+ VStack {
+ //... your app content
+ }
+ .onOpenURL { url in
+ // Call the tracking endpoint with the full deep link URL
+ trackDeepLinkClick(deepLink: url.absoluteString)
+ }
+ }
+ }
+}
+```
+
```kotlin Android
// MainActivity.kt
override fun onNewIntent(intent: Intent?) {
diff --git a/conversions/leads/appwrite.mdx b/conversions/leads/appwrite.mdx
index 15e3ba7b..297ff496 100644
--- a/conversions/leads/appwrite.mdx
+++ b/conversions/leads/appwrite.mdx
@@ -7,7 +7,7 @@ description: "Learn how to track lead conversion events with Appwrite and Dub"
import LeadsIntro from "/snippets/leads-intro.mdx";
import ConversionTrackingPrerequisites from "/snippets/conversion-tracking-prerequisites.mdx";
-import LeadsAttributes from "/snippets/leads-attributes.mdx";
+import LeadAttributes from "/snippets/lead-attributes.mdx";
import LeadsOutro from "/snippets/leads-outro.mdx";
@@ -233,7 +233,7 @@ Next, configure Appwrite to track lead conversion events during the sign up proc
-
+
## Example App
diff --git a/conversions/leads/auth0.mdx b/conversions/leads/auth0.mdx
index a3eba0ae..2daeb606 100644
--- a/conversions/leads/auth0.mdx
+++ b/conversions/leads/auth0.mdx
@@ -7,7 +7,7 @@ description: "Learn how to track lead conversion events with Auth0 and Dub"
import LeadsIntro from "/snippets/leads-intro.mdx";
import ConversionTrackingPrerequisites from "/snippets/conversion-tracking-prerequisites.mdx";
-import LeadsAttributes from "/snippets/leads-attributes.mdx";
+import LeadAttributes from "/snippets/lead-attributes.mdx";
import LeadsOutro from "/snippets/leads-outro.mdx";
@@ -63,6 +63,6 @@ export default handleAuth({
});
```
-
+
diff --git a/conversions/leads/better-auth.mdx b/conversions/leads/better-auth.mdx
index bab58cd8..d3fea613 100644
--- a/conversions/leads/better-auth.mdx
+++ b/conversions/leads/better-auth.mdx
@@ -8,7 +8,7 @@ description: "Learn how to track lead conversion events with Better Auth and Dub
import LeadsIntro from "/snippets/leads-intro.mdx";
import ConversionTrackingPrerequisites from "/snippets/conversion-tracking-prerequisites.mdx";
-import LeadsAttributes from "/snippets/leads-attributes.mdx";
+import LeadAttributes from "/snippets/lead-attributes.mdx";
import LeadsOutro from "/snippets/leads-outro.mdx";
diff --git a/conversions/leads/clerk.mdx b/conversions/leads/clerk.mdx
index a5055175..83949fe9 100644
--- a/conversions/leads/clerk.mdx
+++ b/conversions/leads/clerk.mdx
@@ -7,7 +7,7 @@ description: "Learn how to track lead conversion events with Clerk and Dub"
import LeadsIntro from "/snippets/leads-intro.mdx";
import ConversionTrackingPrerequisites from "/snippets/conversion-tracking-prerequisites.mdx";
-import LeadsAttributes from "/snippets/leads-attributes.mdx";
+import LeadAttributes from "/snippets/lead-attributes.mdx";
import LeadsOutro from "/snippets/leads-outro.mdx";
@@ -233,7 +233,7 @@ Here's a quick summary of the steps:
-
+
## Example App
diff --git a/conversions/leads/client-side.mdx b/conversions/leads/client-side.mdx
index 9c974815..9ad28e67 100644
--- a/conversions/leads/client-side.mdx
+++ b/conversions/leads/client-side.mdx
@@ -29,7 +29,7 @@ Client-Side Conversion Tracking Limitations:
- **Network issues** – Failed network requests won’t retry automatically.
- **Privacy concerns** – Some users may block client-side tracking for privacy reasons.
-For more accurate conversion tracking, consider using [server-side conversion tracking](/docs/conversions/leads/introduction)
+For more accurate conversion tracking, consider using [server-side conversion tracking](/conversions/leads/introduction)
diff --git a/conversions/leads/deferred.mdx b/conversions/leads/deferred.mdx
index 2a8f5151..d9d9a05f 100644
--- a/conversions/leads/deferred.mdx
+++ b/conversions/leads/deferred.mdx
@@ -6,7 +6,7 @@ description: Learn how to track a deferred lead conversion event with Dub
import LeadsIntro from "/snippets/leads-intro.mdx";
import ConversionTrackingPrerequisites from "/snippets/conversion-tracking-prerequisites.mdx";
-import LeadsAttributes from "/snippets/leads-attributes.mdx";
+import LeadAttributes from "/snippets/lead-attributes.mdx";
import LeadsOutro from "/snippets/leads-outro.mdx";
diff --git a/conversions/leads/google-tag-manager.mdx b/conversions/leads/google-tag-manager.mdx
index d874f1d8..95f1ac44 100644
--- a/conversions/leads/google-tag-manager.mdx
+++ b/conversions/leads/google-tag-manager.mdx
@@ -7,7 +7,7 @@ og:image: https://assets.dub.co/cms/gtm-integration.jpeg
import LeadsIntro from "/snippets/leads-intro.mdx";
import ConversionTrackingPrerequisites from "/snippets/conversion-tracking-prerequisites.mdx";
-import LeadsAttributes from "/snippets/leads-attributes.mdx";
+import LeadAttributes from "/snippets/lead-attributes.mdx";
import LeadsOutro from "/snippets/leads-outro.mdx";
@@ -209,7 +209,7 @@ Under the **Triggering** section, configure when the tag should fire:
- **Value**: "Sign Up"
- Name the trigger "Dub Lead Event Trigger" and save it
-
+
## Testing your setup
diff --git a/conversions/leads/introduction.mdx b/conversions/leads/introduction.mdx
index f7b5b109..456a1007 100644
--- a/conversions/leads/introduction.mdx
+++ b/conversions/leads/introduction.mdx
@@ -8,7 +8,7 @@ description: Learn how to track lead conversion events with Dub using server-sid
import LeadsIntro from "/snippets/leads-intro.mdx";
import ConversionTrackingPrerequisites from "/snippets/conversion-tracking-prerequisites.mdx";
import AuthProviders from "/snippets/auth-providers.mdx";
-import LeadsAttributes from "/snippets/leads-attributes.mdx";
+import LeadAttributes from "/snippets/lead-attributes.mdx";
import LeadsOutro from "/snippets/leads-outro.mdx";
@@ -167,5 +167,5 @@ if ($dubId) {
-
+
diff --git a/conversions/leads/next-auth.mdx b/conversions/leads/next-auth.mdx
index 8e68a84c..a455b9de 100644
--- a/conversions/leads/next-auth.mdx
+++ b/conversions/leads/next-auth.mdx
@@ -7,7 +7,7 @@ description: "Learn how to track lead conversion events with NextAuth.js and Dub
import LeadsIntro from "/snippets/leads-intro.mdx";
import ConversionTrackingPrerequisites from "/snippets/conversion-tracking-prerequisites.mdx";
-import LeadsAttributes from "/snippets/leads-attributes.mdx";
+import LeadAttributes from "/snippets/lead-attributes.mdx";
import LeadsOutro from "/snippets/leads-outro.mdx";
@@ -108,7 +108,7 @@ export const getOptions = (req: NextApiRequest): NextAuthOptions => ({
`callback`](https://next-auth.js.org/configuration/callbacks) instead.
-
+
## Create a NextAuth.js Route Handler
diff --git a/conversions/leads/segment.mdx b/conversions/leads/segment.mdx
index 8b9985b2..c94d9363 100644
--- a/conversions/leads/segment.mdx
+++ b/conversions/leads/segment.mdx
@@ -7,7 +7,7 @@ description: "Learn how to track lead conversion events with Segment and Dub"
import LeadsIntro from "/snippets/leads-intro.mdx";
import ConversionTrackingPrerequisites from "/snippets/conversion-tracking-prerequisites.mdx";
-import LeadsAttributes from "/snippets/leads-attributes.mdx";
+import LeadAttributes from "/snippets/lead-attributes.mdx";
import LeadsOutro from "/snippets/leads-outro.mdx";
@@ -133,7 +133,7 @@ Next, configure [Segment Dub (Actions)](https://app.segment.com/goto-my-workspac
-
+
## Example App
diff --git a/conversions/leads/supabase.mdx b/conversions/leads/supabase.mdx
index 01e78339..93333106 100644
--- a/conversions/leads/supabase.mdx
+++ b/conversions/leads/supabase.mdx
@@ -7,7 +7,7 @@ description: "Learn how to track lead conversion events with Supabase and Dub"
import LeadsIntro from "/snippets/leads-intro.mdx";
import ConversionTrackingPrerequisites from "/snippets/conversion-tracking-prerequisites.mdx";
-import LeadsAttributes from "/snippets/leads-attributes.mdx";
+import LeadAttributes from "/snippets/lead-attributes.mdx";
import LeadsOutro from "/snippets/leads-outro.mdx";
@@ -137,7 +137,7 @@ export default async function handler(
-
+
## Example App
diff --git a/conversions/quickstart.mdx b/conversions/quickstart.mdx
index e6f2c713..121d386d 100644
--- a/conversions/quickstart.mdx
+++ b/conversions/quickstart.mdx
@@ -12,7 +12,7 @@ import ViewConversions from "/snippets/view-conversions.mdx";
import DubConversionTrackingDemoApps from "/snippets/dub-conversion-tracking-demo-apps.mdx";
- Conversion tracking require a [Business plan](https://dub.co/pricing)
+ Conversion tracking requires a [Business plan](https://dub.co/pricing)
subscription or higher.
diff --git a/conversions/sales/client-side.mdx b/conversions/sales/client-side.mdx
index f8a4094b..866eed76 100644
--- a/conversions/sales/client-side.mdx
+++ b/conversions/sales/client-side.mdx
@@ -31,7 +31,7 @@ Client-Side Conversion Tracking Limitations:
- **Network issues** – Failed network requests won’t retry automatically.
- **Privacy concerns** – Some users may block client-side tracking for privacy reasons.
-For more accurate conversion tracking, consider using [server-side conversion tracking](/docs/conversions/sales/introduction)
+For more accurate conversion tracking, consider using [server-side conversion tracking](/conversions/sales/introduction)
diff --git a/conversions/sales/google-tag-manager.mdx b/conversions/sales/google-tag-manager.mdx
index ad7b69ae..2edb9fc5 100644
--- a/conversions/sales/google-tag-manager.mdx
+++ b/conversions/sales/google-tag-manager.mdx
@@ -10,7 +10,7 @@ import SalesAttributes from "/snippets/sale-attributes.mdx";
import ViewConversions from "/snippets/view-conversions.mdx";
- Conversion tracking require a [Business plan](https://dub.co/pricing)
+ Conversion tracking requires a [Business plan](https://dub.co/pricing)
subscription or higher.
diff --git a/conversions/sales/shopify.mdx b/conversions/sales/shopify.mdx
index 263ecb76..c5080cd6 100644
--- a/conversions/sales/shopify.mdx
+++ b/conversions/sales/shopify.mdx
@@ -8,7 +8,7 @@ description: "Learn how to track sale conversion events with Shopify and Dub"
import ViewConversions from "/snippets/view-conversions.mdx";
- Conversion tracking require a [Business plan](https://dub.co/pricing)
+ Conversion tracking requires a [Business plan](https://dub.co/pricing)
subscription or higher.
diff --git a/docs.json b/docs.json
index 05ee4de3..57c7938d 100644
--- a/docs.json
+++ b/docs.json
@@ -128,6 +128,7 @@
"pages": [
"api-reference/introduction",
"api-reference/tokens",
+ "api-reference/publishable-keys",
"api-reference/rate-limits"
]
},
@@ -146,7 +147,7 @@
]
},
{
- "group": "Client-side SDK",
+ "group": "Client-side SDK (Web)",
"pages": [
"sdks/client-side/introduction",
{
@@ -174,8 +175,16 @@
]
},
{
- "group": "Embedded Dashboards",
- "pages": ["sdks/embed/referrals", "sdks/embed/analytics"]
+ "group": "Client-side SDK (Mobile)",
+ "pages": [
+ "sdks/client-side-mobile/introduction",
+ {
+ "group": "Installation Guides",
+ "pages": [
+ "sdks/client-side-mobile/installation-guides/swift"
+ ]
+ }
+ ]
}
]
},
diff --git a/integrations/quickstart.mdx b/integrations/quickstart.mdx
index ae0614d1..a7cffe8a 100644
--- a/integrations/quickstart.mdx
+++ b/integrations/quickstart.mdx
@@ -216,7 +216,7 @@ Dub supports the following scopes for OAuth 2.0:
| `analytics.read` | Read access to analytics. |
| `domains.read` | Read access to domains. |
| `domains.write` | Write access to domains. |
-| `folders.read` | Read access to folders. |
+| `folders.read` | Read access to folders. |
| `folders.write` | Write access to folders. |
| `user.read` | Read access to user information. This scope is included by default. |
diff --git a/partners/quickstart.mdx b/partners/quickstart.mdx
index da7f8782..99ee324d 100644
--- a/partners/quickstart.mdx
+++ b/partners/quickstart.mdx
@@ -39,14 +39,14 @@ This script detects the `dub_id` query parameter and storing it as a first-party
On top of that, it also:
-- lets you [track clicks on the client-side](/sdks/client-side/features/client-side-click-tracking) using query parameters (e.g. `?via=john`)
-- [automatically fetch the partner and discount data](/sdks/client-side/features/client-side-click-tracking#automatically-fetching-partner-and-discount-data) for a given link – which is helpful for displaying [dual-sided incentives](https://dub.co/help/article/dual-sided-incentives)
+- lets you [track clicks on the client-side](/sdks/client-side/features/click-tracking) using query parameters (e.g. `?via=john`)
+- [automatically fetch the partner and discount data](/sdks/client-side/features/click-tracking#automatically-fetching-partner-and-discount-data) for a given link – which is helpful for displaying [dual-sided incentives](https://dub.co/help/article/dual-sided-incentives)
-Once the script is installed, make sure to verify that [client-side click tracking](/sdks/client-side/features/client-side-click-tracking) is working as expected by checking if the following is true:
+Once the script is installed, make sure to verify that [client-side click tracking](/sdks/client-side/features/click-tracking) is working as expected by checking if the following is true:
diff --git a/sdks/client-side-mobile/installation-guides/swift.mdx b/sdks/client-side-mobile/installation-guides/swift.mdx
new file mode 100644
index 00000000..b475a8ef
--- /dev/null
+++ b/sdks/client-side-mobile/installation-guides/swift.mdx
@@ -0,0 +1,37 @@
+---
+title: Swift
+description: How to add the Dub iOS SDK to your Swift project
+---
+
+import DubSwiftInstall from "/snippets/dub-client-mobile-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 allowlist your site's domain (`DUB_DOMAIN`) to allow the client-side conversion events to be ingested by Dub.
+
+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 iOS SDK in your Swift project.
+
+
+
+## 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/introduction.mdx b/sdks/client-side-mobile/introduction.mdx
new file mode 100644
index 00000000..724c578c
--- /dev/null
+++ b/sdks/client-side-mobile/introduction.mdx
@@ -0,0 +1,40 @@
+---
+title: Introduction
+description: Learn more about the the Dub client-side mobile SDKs.
+---
+
+import InstallationGuides from "/snippets/dub-client-mobile-installation-guides.mdx";
+import DubAnalyticsParams from "/snippets/dub-analytics-params.mdx";
+
+Dub offers first-party, open-source, mobile SDKs to help you track [deep links](/concepts/deep-links/quickstart), [deferred deep links](/concepts/deep-links/deferred-deep-linking), and [deep link attribution](/concepts/deep-links/attribution) in your mobile applications.
+
+Currently, we support the following mobile SDKs:
+
+- [Dub iOS SDK](https://github.com/dubinc/dub-ios)
+
+
+ React Native and Android support are 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:
+
+
+
+## Open-source examples
+
+Here are some open-source code examples that you can reference:
+
+
+
+ See the full example on GitHub.
+
+
diff --git a/sdks/client-side/installation-guides/google-tag-manager.mdx b/sdks/client-side/installation-guides/google-tag-manager.mdx
index 37451a26..ae1e22f5 100644
--- a/sdks/client-side/installation-guides/google-tag-manager.mdx
+++ b/sdks/client-side/installation-guides/google-tag-manager.mdx
@@ -47,7 +47,7 @@ This guide will walk you through the process of integrating Dub Analytics with G
- If you're using [Dub Partners](/partners/quickstart) for affiliate management, you will also need to set up the `data-domains` property to enable [client-side click-tracking](/sdks/client-side/features/client-side-click-tracking).
+ If you're using [Dub Partners](/partners/quickstart) for affiliate management, you will also need to set up the `data-domains` property to enable [client-side click-tracking](/sdks/client-side/features/click-tracking).
```js
```
-Read the [client-side click-tracking guide](/sdks/client-side/features/client-side-click-tracking) for more information.
+Read the [client-side click-tracking guide](/sdks/client-side/features/click-tracking) for more information.
diff --git a/snippets/client-side-lead-tracking.mdx b/snippets/client-side-lead-tracking.mdx
index 0b3eb062..6df8e920 100644
--- a/snippets/client-side-lead-tracking.mdx
+++ b/snippets/client-side-lead-tracking.mdx
@@ -1,4 +1,4 @@
-import LeadsAttributes from "/snippets/leads-attributes.mdx";
+import LeadAttributes from "/snippets/lead-attributes.mdx";
Once the analytics script is installed, you can start tracking lead events in your application on the client-side.
@@ -85,7 +85,7 @@ export function SignUpForm() {
-
+
**When to track leads**
diff --git a/snippets/client-side-tracking-install.mdx b/snippets/client-side-tracking-install.mdx
index bcdd5321..7a8c5fdc 100644
--- a/snippets/client-side-tracking-install.mdx
+++ b/snippets/client-side-tracking-install.mdx
@@ -1,49 +1,13 @@
+import GeneratePublishableKeyStep from "/snippets/steps/generate-publishable-key.mdx";
+import AllowlistDomainsStep from "/snippets/steps/allowlist-domains.mdx";
+
Then, you'll need to install the Dub client-side script and set up the necessary configuration for client-side conversion tracking:
-
-
-Before you can track conversions on the client-side, you need to generate a publishable key from your Dub workspace.
-
-To do that, navigate to your [workspace's Analytics settings page](https://app.dub.co/settings/analytics) and generate a new publishable key under the **Publishable Key** section.
-
-
-
-
-
-
-
-
-
-Then, you'll need to allowlist your site's domain to allow the client-side conversion events to be ingested by Dub.
+
-To do that, navigate to your [workspace's Analytics settings page](https://app.dub.co/settings/analytics) and add your site's domain to the **Allowed Hostnames** list.
-
-This provides an additional layer of security by ensuring only authorized domains can track conversions using your publishable key.
-
-
-
-
-
-You can group your hostnames when adding them to the allow list:
-
-- `example.com`: Tracks traffic **only** from `example.com`.
-- `*.example.com`: Tracks traffic from **all subdomains** of `example.com`, but **not** from `example.com` itself.
-
-
- When testing things out locally, you can add `localhost` to the **Allowed
- Hostnames** list temporarily. This will allow local events to be ingested by
- Dub. Don't forget to remove it once you're ready to go live!
-
-
-
+
diff --git a/snippets/dub-analytics-install.mdx b/snippets/dub-analytics-install.mdx
index ea6455bd..d5385657 100644
--- a/snippets/dub-analytics-install.mdx
+++ b/snippets/dub-analytics-install.mdx
@@ -50,7 +50,7 @@
- If you're using [Dub Partners](/partners/quickstart) for affiliate management, you will also need to set up the `domainsConfig.refer` property to enable [client-side click-tracking](/sdks/client-side/features/client-side-click-tracking).
+ If you're using [Dub Partners](/partners/quickstart) for affiliate management, you will also need to set up the `domainsConfig.refer` property to enable [client-side click-tracking](/sdks/client-side/features/click-tracking).
```jsx app/layout.tsx
import { Analytics as DubAnalytics } from '@dub/analytics/react';
@@ -71,7 +71,7 @@
}
```
- Read the [client-side click-tracking guide](/sdks/client-side/features/client-side-click-tracking) for more information.
+ Read the [client-side click-tracking guide](/sdks/client-side/features/click-tracking) for more information.
diff --git a/snippets/dub-client-mobile-install.mdx b/snippets/dub-client-mobile-install.mdx
new file mode 100644
index 00000000..c6b44bad
--- /dev/null
+++ b/snippets/dub-client-mobile-install.mdx
@@ -0,0 +1,224 @@
+import LeadAttributes from "/snippets/lead-attributes.mdx";
+import SaleAttributes from "/snippets/sale-attributes.mdx";
+
+
+
+ Before installing, ensure your environment meets these minimum requirements:
+
+**Build Tools:**
+
+- Xcode 16+
+- Swift 6+
+
+**Platforms:**
+
+- iOS 16.0+
+- macOS 10.13 (Ventura)+
+
+The Dub iOS SDK can be installed using the [Swift Package Manager](https://docs.swift.org/swiftpm/documentation/packagemanagerdocs/).
+
+In Xcode, select **File** > **Add Package Dependencies** and add `https://github.com/dubinc/dub-ios` as the repository URL. Select the latest version of the SDK from the [release page](https://github.com/dubinc/dub-ios/releases).
+
+
+
+
+
+You must call `Dub.setup` with your publishable key and domain prior to being able to use the `dub` instance.
+
+
+
+```swift iOS (SwiftUI)
+import SwiftUI
+import Dub
+
+@main
+struct DubApp: App {
+ // Step 1: Obtain your Dub domain and publishable key
+ private let dubPublishableKey = ""
+ private let dubDomain = ""
+
+ init() {
+ // Step 2: Initialize the Dub SDK by calling `setup`
+ Dub.setup(publishableKey: dubPublishableKey, domain: dubDomain)
+ }
+
+ var body: some Scene {
+ WindowGroup {
+ ContentView()
+ // Step 3: Expose the `dub` instance as a SwiftUI environment value
+ .environment(\.dub, Dub.shared)
+ }
+ }
+}
+```
+
+
+
+
+
+
+ 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.
+
+
+
+```swift iOS (SwiftUI) expandable
+// ContentView.swift
+import SwiftUI
+import Dub
+
+struct ContentView: View {
+
+ @Environment(\.dub) var dub: Dub
+
+ @AppStorage("is_first_launch") private var isFirstLaunch = true
+
+ var body: some View {
+ NavigationStack {
+ VStack {
+ // Your app content
+ }
+ .onOpenURL { url in
+ trackOpen(deepLink: url)
+ }
+ .onAppear {
+ if isFirstLaunch {
+ trackOpen()
+ isFirstLaunch = false
+ }
+ }
+ }
+ }
+
+ private func trackOpen(deepLink: URL? = nil) {
+ Task {
+ do {
+ let response = try await dub.trackOpen(deepLink: deepLink)
+
+ // Obtain the destination URL from the response
+ guard let url = response.link?.url else {
+ return
+ }
+
+ // Navigate to the destination URL
+ } catch let error as DubError {
+ print(error.localizedDescription)
+ }
+ }
+ }
+}
+```
+
+
+
+
+
+
+
+To track lead events, call `trackLead` on the `dub` instance with your customer's external ID, name, and email.
+
+
+
+```swift iOS (SwiftUI) expandable
+// ContentView.swift
+import SwiftUI
+import Dub
+
+struct ContentView: View {
+
+ @Environment(\.dub) var dub: Dub
+
+ var body: some View {
+ // ... your app content ...
+ }
+
+ private func trackLead(customerExternalId: String, name: String, email: String) {
+ Task {
+ do {
+ let response = try await dub.trackLead(
+ eventName: "User Sign Up",
+ customerExternalId: customerExternalId,
+ customerName: name,
+ customerEmail: email
+ )
+
+ print(response)
+ } catch let error as DubError {
+ print(error.localizedDescription)
+ }
+ }
+ }
+}
+```
+
+
+
+
+
+
+
+
+
+
+
+ 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
+import SwiftUI
+import Dub
+
+struct ContentView: View {
+
+ @Environment(\.dub) var dub: Dub
+
+ var body: some View {
+ // ... your app content ...
+ }
+
+ 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.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
new file mode 100644
index 00000000..8510021d
--- /dev/null
+++ b/snippets/dub-client-mobile-installation-guides.mdx
@@ -0,0 +1,10 @@
+
+
+
+ Add the Dub iOS SDK to your app (Swift)
+
+
diff --git a/snippets/leads-attributes.mdx b/snippets/lead-attributes.mdx
similarity index 100%
rename from snippets/leads-attributes.mdx
rename to snippets/lead-attributes.mdx
diff --git a/snippets/leads-intro.mdx b/snippets/leads-intro.mdx
index 7165e260..cd2eae13 100644
--- a/snippets/leads-intro.mdx
+++ b/snippets/leads-intro.mdx
@@ -1,5 +1,5 @@
- Conversion tracking require a [Business plan](https://dub.co/pricing)
+ Conversion tracking requires a [Business plan](https://dub.co/pricing)
subscription or higher.
diff --git a/snippets/sales-intro.mdx b/snippets/sales-intro.mdx
index bcaebcb8..a061d54a 100644
--- a/snippets/sales-intro.mdx
+++ b/snippets/sales-intro.mdx
@@ -1,5 +1,5 @@
- Conversion tracking require a [Business plan](https://dub.co/pricing)
+ Conversion tracking requires a [Business plan](https://dub.co/pricing)
subscription or higher.
diff --git a/snippets/steps/allowlist-domains.mdx b/snippets/steps/allowlist-domains.mdx
new file mode 100644
index 00000000..f6d7c5dc
--- /dev/null
+++ b/snippets/steps/allowlist-domains.mdx
@@ -0,0 +1,27 @@
+
+
+Then, you'll need to allowlist your site's domain to allow the client-side conversion events to be ingested by Dub.
+
+To do that, navigate to your [workspace's Analytics settings page](https://app.dub.co/settings/analytics) and add your site's domain to the **Allowed Hostnames** list.
+
+This provides an additional layer of security by ensuring only authorized domains can track conversions using your publishable key.
+
+
+
+
+
+You can group your hostnames when adding them to the allow list:
+
+- `example.com`: Tracks traffic **only** from `example.com`.
+- `*.example.com`: Tracks traffic from **all subdomains** of `example.com`, but **not** from `example.com` itself.
+
+
+ When testing things out locally, you can add `localhost` to the **Allowed
+ Hostnames** list temporarily. This will allow local events to be ingested by
+ Dub. Don't forget to remove it once you're ready to go live!
+
+
+
diff --git a/snippets/steps/generate-publishable-key.mdx b/snippets/steps/generate-publishable-key.mdx
new file mode 100644
index 00000000..871de215
--- /dev/null
+++ b/snippets/steps/generate-publishable-key.mdx
@@ -0,0 +1,14 @@
+
+
+Before you can track conversions on the client-side, you need to generate a [publishable key](/api-reference/publishable-keys) from your Dub workspace.
+
+To do that, navigate to your [workspace's Analytics settings page](https://app.dub.co/settings/analytics) and generate a new publishable key under the **Publishable Key** section.
+
+
+
+
+
+
diff --git a/snippets/steps/initialize-ios-sdk.mdx b/snippets/steps/initialize-ios-sdk.mdx
new file mode 100644
index 00000000..2b93f0b4
--- /dev/null
+++ b/snippets/steps/initialize-ios-sdk.mdx
@@ -0,0 +1,29 @@
+
+
+You must call `Dub.setup` with your publishable key and domain prior to being able to use the `dub` instance.
+
+```swift iOS (SwiftUI)
+import SwiftUI
+import Dub
+
+@main
+struct DubApp: App {
+ // Step 1: Obtain your Dub domain and publishable key
+ private let dubPublishableKey = ""
+ private let dubDomain = ""
+
+ init() {
+ // Step 2: Initialize the Dub SDK by calling `setup`
+ Dub.setup(publishableKey: dubPublishableKey, domain: dubDomain)
+ }
+
+ var body: some Scene {
+ WindowGroup {
+ ContentView()
+ // Step 3: Expose the `dub` instance as a SwiftUI environment value
+ .environment(\.dub, Dub.shared)
+ }
+ }
+}
+```
+
diff --git a/snippets/steps/install-ios-sdk.mdx b/snippets/steps/install-ios-sdk.mdx
new file mode 100644
index 00000000..517babaa
--- /dev/null
+++ b/snippets/steps/install-ios-sdk.mdx
@@ -0,0 +1,16 @@
+
+Before installing, ensure your environment meets these minimum requirements:
+
+**Build Tools:**
+- Xcode 16+
+- Swift 6+
+
+**Platforms:**
+- iOS 16.0+
+- macOS 10.13 (Ventura)+
+
+The Dub iOS SDK can be installed using the [Swift Package Manager](https://docs.swift.org/swiftpm/documentation/packagemanagerdocs/).
+
+In Xcode, select **File** > **Add Package Dependencies** and add `https://github.com/dubinc/dub-ios` as the repository URL. Select the latest version of the SDK from the [release page](https://github.com/dubinc/dub-ios/releases).
+
+
\ No newline at end of file