Firebase Dynamic Links

Create a short Firebase Dynamic Link from your server.

Set inputs from the environment

Each required value can be passed inline or read from an environment variable. Only deepLinkUrl has no env fallback — always pass it.

  • firebaseWebApiKeyBDK_FIREBASE_WEB_API_KEY, FIREBASE_WEB_API_KEY, FIREBASE_DYNAMIC_LINKS_WEB_API_KEY
  • domainUriPrefixBDK_FIREBASE_DYNAMIC_LINK_DOMAIN_URI_PREFIX, FIREBASE_DYNAMIC_LINK_DOMAIN_URI_PREFIX
  • iosBundleIdBDK_IOS_BUNDLE_ID, IOS_BUNDLE_ID
  • iosAppStoreIdBDK_IOS_APPSTORE_ID, IOS_APPSTORE_ID, IOS_APP_STORE_ID
  • androidPackageNameBDK_ANDROID_BUNDLE_ID, ANDROID_BUNDLE_ID, ANDROID_PACKAGE_NAME

A domainUriPrefix with no scheme gets https:// prepended.

A missing required value (in both input and environment) throws a BdkError with code BDK_VALIDATION_ERROR before any network request.

// With BDK_FIREBASE_WEB_API_KEY, *_DOMAIN_URI_PREFIX, IOS_BUNDLE_ID,
// IOS_APPSTORE_ID, and ANDROID_PACKAGE_NAME set in the environment:
import { createFirebaseDynamicLink } from "@bdk/native/server/firebase-dynamic-links";

const result = await createFirebaseDynamicLink({
  deepLinkUrl: "https://example.com/promo"
});

Read the result

The promise resolves to a FirebaseDynamicLinkResult. Check dynamicLink or errorMessage before using the link.

  • dynamicLink: string | null — the short link, or null on failure.
  • previewLink: string | null — the preview link, or null if absent.
  • errorMessage: string | nullnull on success, otherwise the API error.
  • raw: unknown — the full JSON response.

A failed API call does not throw — it returns dynamicLink: null with errorMessage set, so always branch on one of those.

const result = await createFirebaseDynamicLink({
  deepLinkUrl: "https://example.com/items/42"
});

if (result.errorMessage) {
  // Inspect result.raw for the full Firebase response payload.
  throw new Error(`Dynamic link failed: ${result.errorMessage}`);
}

return {
  link: result.dynamicLink,
  preview: result.previewLink
};

Add query params and redirect options

Shape the URL and redirect behavior of the generated link.

  • urlParams appends query parameters to deepLinkUrl; null/undefined values are dropped.
  • suffixOption sets the path length: "SHORT" (case-insensitive) for a short suffix, otherwise "UNGUESSABLE".
  • enableForcedRedirect: true skips the app preview page.
const result = await createFirebaseDynamicLink({
  deepLinkUrl: "https://example.com/checkout",
  urlParams: { ref: "newsletter", discount: 20 },
  suffixOption: "SHORT",
  enableForcedRedirect: true
});

Set platform fallbacks

Control where users without the app installed are sent with iosFallback and androidFallback (both FirebaseDynamicLinkFallback). The type field (case- and spacing-insensitive) picks the behavior:

  • "app-store-page" / "play-store-page" — sends to the store; the iOS / Android default. No url needed.
  • "same-url" — redirects to deepLinkUrl.
  • "fallback-url" — redirects to a custom url (required), with optional urlParams.

Use iosIpadFallbackUrl for a dedicated iPad fallback.

const result = await createFirebaseDynamicLink({
  deepLinkUrl: "https://example.com/items/42",
  iosFallback: {
    type: "fallback-url",
    url: "https://example.com/get-the-app",
    urlParams: { platform: "ios" }
  },
  androidFallback: { type: "same-url" },
  iosIpadFallbackUrl: "https://example.com/ipad"
});

Add a social preview and analytics tags

Add a rich preview card or campaign tracking. Empty sections are omitted from the request.

  • social (FirebaseDynamicLinkSocial) — the preview card: title, description, imageUrl.
  • googlePlayAnalytics (FirebaseGooglePlayAnalytics) — UTM params (utmSource, utmMedium, utmCampaign, utmTerm, utmContent) plus gclid.
  • itunesConnectAnalytics (FirebaseItunesConnectAnalytics) — Apple campaign fields at, ct, mt, pt.
const result = await createFirebaseDynamicLink({
  deepLinkUrl: "https://example.com/promo",
  social: {
    title: "Summer Sale",
    description: "Up to 50% off — open in the app.",
    imageUrl: "https://example.com/og.png"
  },
  googlePlayAnalytics: {
    utmSource: "newsletter",
    utmMedium: "email",
    utmCampaign: "summer_2026"
  },
  itunesConnectAnalytics: {
    at: "affiliate-token",
    ct: "summer_2026"
  }
});

Use a custom endpoint or fetch

Point at a different endpoint or inject a fetch for testing or proxying. Set baseUrl (default https://firebasedynamiclinks.googleapis.com/v1) and pass a fetch (FetchLike) matching the global fetch signature.

const result = await createFirebaseDynamicLink({
  deepLinkUrl: "https://example.com/items/42",
  baseUrl: "https://my-proxy.internal/firebase/v1",
  fetch: myCustomFetch
});