Creating Dynamic Links and Deep Linking URLs in Node.js for React Native
Suraj Prasad
Posted on August 5, 2024
In the mobile app ecosystem, providing a seamless user experience is critical. One way to enhance this is by implementing deep links and dynamic links within your app. Dynamic links allow you to share content and ensure users have a smooth transition whether they have your app installed or not. In this blog, we'll explore how to create dynamic links and deep linking URLs using Node.js for a React Native application.
What Are Dynamic Links and Deep Links?
Deep Links: These are URLs that take users to a specific part of your app. When users click on a deep link, the app opens to the specific content the link is meant to display. If the app is not installed, the link typically opens the web version of the app or a fallback page.
Dynamic Links: These are deep links with added flexibility. They can change their behavior based on different conditions, such as whether the app is installed, the platform (iOS or Android), or even the context in which the link is opened (e.g., marketing campaigns).
Why Use Dynamic Links?
Cross-Platform Compatibility: Dynamic links work on multiple platforms, including iOS, Android, and web.
Deferred Deep Linking: If the app isn't installed, dynamic links can direct users to the app store and then to the specific content once the app is installed.
Enhanced User Experience: They provide a more personalized experience by directing users to the right content within your app.
Prerequisites
Before we dive in, make sure you have the following:
Node.js installed on your machine.
A React Native project setup.
Firebase account (optional, but recommended for generating dynamic links).
Step 1: Setting Up a Node.js Server
We'll start by setting up a Node.js server that will generate dynamic links. You can use Express.js to create a simple server.
First, create a new Node.js project:
mkdir dynamic-links-server
cd dynamic-links-server
npm init -y
npm install express shortid
Step 2: Generating Dynamic Links
const express = require("express");
const shortId = require("shortid")
const { appendSeoDetail } = require("./utils");
const app = express()
const PORT = process.env.PORT || 3000
app.use(express.json())
app.use("/.well-known", express.static('.well-known'))
const urls = {};
app.post("/create-url", (req, res) => {
try {
const { title, description, image, newsId } = req.body
const previewUrl = `https://3a09-2402-4cc0-2501-1f4-71ad-7a58-7a4c-895c.ngrok-free.app/?newsId=${newsId}&title=${encodeURIComponent(title)}&description=${encodeURIComponent(description)}&image=${encodeURIComponent(image)}`
const id = shortId.generate();
urls[id] = previewUrl;
res.send({ url: `https://3a09-2402-4cc0-2501-1f4-71ad-7a58-7a4c-895c.ngrok-free.app/${id}` })
} catch (error) {
res.send({ error: "Something went wrong" })
}
})
app.get('/:id', (req, res) => {
const id = req.params.id;
const url = urls[id];
if (url) {
res.redirect(url);
} else {
res.sendStatus(404);
}
});
app.get('*', (req, res,) => {
const { title, description, image } = req.query
// Define values
const source = appendSeoDetail({ title, description, image })
// Return the webpage
return res.send(source);
});
app.listen(PORT, () => {
console.log("App is running on ", PORT)
})
Step 3: Creating index html for the social share preview
<!DOCTYPE html>
<html lang="en">
<head>
<!-- HTML Meta Tags -->
<title>{{title}}</title>
<meta name="description" content="{{description}}" />
<!-- Facebook Meta Tags -->
<meta property="og:url" content="https://3a09-2402-4cc0-2501-1f4-71ad-7a58-7a4c-895c.ngrok-free.app/" />
<meta property="og:type" content="website" />
<meta property="og:title" content="{{title}}" />
<meta property="og:description" content="{{description}}" />
<meta property="og:image" content="{{image}}" />
<!-- Twitter Meta Tags -->
<meta name="twitter:card" content="summary_large_image" />
<meta property="twitter:domain" content="3a09-2402-4cc0-2501-1f4-71ad-7a58-7a4c-895c.ngrok-free.app" />
<meta property="twitter:url" content="https://3a09-2402-4cc0-2501-1f4-71ad-7a58-7a4c-895c.ngrok-free.app/" />
<meta name="twitter:title" content="{{title}}" />
<meta name="twitter:description" content="{{description}}" />
<meta name="twitter:image" content="{{image}}" />
<!-- Meta Tags Generated via https://www.opengraph.xyz -->
<link
rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/bootstrap@4.0.0/dist/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous"
/>
<script
src="https://cdnjs.cloudflare.com/ajax/libs/Detect.js/2.2.2/detect.min.js"
rossorigin="anonymous"
referrerpolicy="no-referrer"
></script>
</head>
<body>
<div class="container pt-3">
<div class="text-center row justify-content-center">
<div class="col-10">
<a href="#">
<img src="https://www.pouch.news/cropped-pulse%201.png" class="img-fluid" alt="" />
</a>
</div>
</div>
<div class="centered row mt-3 justify-content-center align-items-center">
<div class="col-md-3 col-10 text-center">
<p id="message"></p>
<p id="redirectMessage text-center d-none d-md-block">Redirecting you to Example app.</p>
</div>
</div>
</div>
</body>
<script>
// Function to check if it's an Android device
function isAndroid() {
return navigator.userAgent.match(/Android/i)
}
// Function to check if it's an iOS device
function isiOS() {
return navigator.userAgent.match(/iPhone|iPad|iPod/i)
}
// Function to check if it's a desktop
function isDesktop() {
return window.innerWidth > 768 // Adjust the width threshold as needed
}
// Function to redirect to a website
function redirectToWebsite() {
window.location.href = "https://www.example.com/" // Replace with your desired URL
}
// Function to redirect to the Google Play Store
function redirectToPlayStore() {
window.location.href =
"intent://details?id=com.example#Intent;scheme=market;package=com.example;end"
}
// Function to redirect to the App Store
function redirectToAppStore() {
window.location.href = "itms-apps://itunes.apple.com/app/appid2323" // Replace with your app's App Store URL
}
// Check the device type and display the appropriate message
if (isDesktop()) {
redirectToWebsite()
} else if (isAndroid()) {
document.getElementById("message").textContent =
"We are redirecting you to the examplemobile app for Android."
setTimeout(redirectToPlayStore, 3000) // Redirect after 3 seconds
} else if (isiOS()) {
document.getElementById("message").textContent = "We are redirecting you to the examplemobile app for iOS."
setTimeout(redirectToAppStore, 3000) // Redirect after 3 seconds
}
</script>
</html>
Step 4: Creating utils for the appending dynamic seo title
const path = require("path")
const fs = require("fs");
function appendSeoDetail({ title, description, image }) {
const _title = title ?? 'POUCH - Packaging News App';
const _subtitle = description ?? 'Pouch is a news aggregator application for the Packaging industry that summarises news articles and stories sourced from various third-party links including industry journals, expert blogs, and innovative company releases';
const _image = image ?? 'https://www.pouch.news/cropped-pulse%201.png';
// Load HTML template
const templatePath = path.join(__dirname, '../index.html');
// Replace handles with content
var source = fs.readFileSync(templatePath, { encoding: 'utf-8' })
.replaceAll('{{title}}', _title)
.replaceAll('{{description}}', _subtitle)
.replaceAll('{{image}}', _image);
return source
}
module.exports = { appendSeoDetail }
Step 5: Make a .well-know folder and insert files for
assetlinks.json and apple-app-site-association
{
"applinks": {
"details": [
{
"appIDs": [
"EXDFF##.com.example"
],
"paths": [
"*"
]
}
]
},
"webcredentials": {
"apps": [
"EXDFF##.com.example"
]
}
}
[
{
"relation": [
"delegate_permission/common.handle_all_urls"
],
"target": {
"namespace": "android_app",
"package_name": "com.example",
"sha256_cert_fingerprints": [
"9B:83:32:66:75:91:03:3B:9C"
]
}
}
]
Step 7: Integrating Deep Links in React Native
const linking = {
prefixes: ["example://", "https://3a09-2402-4cc0-2501-1f4-71ad-7a58-7a4c-895c.ngrok-free.app"],
config,
async getInitialURL() {
const url = await Linking.getInitialURL()
console.log(url, "Dynamic url")
if (typeof url === "string") {
return url
}
js
},
}
<NavigationContainer ref={navigationRef} linking={linking}>
</NavigationContainer>
Conclusion
By setting up dynamic links and deep linking in your React Native app with a Node.js backend, you can significantly enhance the user experience by providing seamless navigation and personalized content. Dynamic links offer a powerful way to ensure that users get to the right content, whether they have your app installed or not.
This setup is not just limited to Firebase. You can use other services like Branch.io or create a custom solution depending on your needs. The principles, however, remain the same: enabling users to move directly to the content they care about.
Happy coding!
Posted on August 5, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.