Firebase dynamic link acting differently if generated on iOS (React Native) vs REST API - firebase

We have a functionality to generate dynamic links to our app on iOS using React Native, which works perfectly (identifiable data redacted by replacing them with "our app"):
dynamicLinks().buildShortLink({
link: `https://our_app?referral=${referralCode}`,
domainUriPrefix: 'https://ourapp.page.link',
android: {
packageName: 'app.ourapp.mobile',
},
ios: {
appStoreId: 'XXX',
bundleId: 'app.ourapp.client',
},
navigation: {
forcedRedirectEnabled: true,
},
});
It correctly opens the app if installed, and App Store if not installed.
I need to implement the same functionality on web site, here's my code:
const payload = {
dynamicLinkInfo: {
link: `https://our_app.app?referral=${referralCode}`,
domainUriPrefix: 'https://ourapp.page.link',
androidInfo: {
androidPackageName: 'app.ourapp.mobile',
},
iosInfo: {
iosBundleId: 'XXX',
iosBundleId: 'app.ourapp.client',
},
navigationInfo: {
enableForcedRedirect: true,
},
}
};
// generate page link and redirect there
const result = await fetch('https://firebasedynamiclinks.googleapis.com/v1/shortLinks?key=OUR_API_KEY', {
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(payload)
});
It's the same (with parameter names from React Native changed to REST parameter names respectively, as documented at https://firebase.google.com/docs/reference/dynamic-links/link-shortener)
A link is generated, however when clicked, if the app isn't installed, the page link redirects our website instead of App Store.
When I debug both links using ?d=1 query string parameter, I can indeed notice the difference:
(left: in-app generated, correct. right: REST-generated, incorrect)
Why are these links, generated with the exact same parameters, behaving differently and how can I make the second one work exactly like the first one (redirect to App Store instead of our website)?

After examining closely I've found a typo:
While generating the link in the second example, I was mistakenly using the same key twice:
iosInfo: {
iosBundleId: 'XXX',
iosBundleId: 'app.ourapp.client',
},
Changed the first one to iosAppStoreId and it worked.

Related

Manually constructing a Dynamic Link URL with OFL Parameter not working on Desktop Browser

I created dynamic link (React-Native App) which is working perfectly on Android & iOS devices but if open same link on desktop browser it say "Dynamic link not found/Invalid dynamic link". I have created custom dynamic link as well as using Firebase dynamic link
--- Using Firebase Link ---
await firebase.dynamicLinks().buildShortLink(
{
domainUriPrefix: `${prefix_url}`,
link: `${prefix_url}/${params}`,
android: {
packageName: `${package_name}`,
},
ios: {
bundleId: `${bundle_id}`,
appStoreId: 'xxxxxxxxxx',
},
otherPlatform: {
fallbackUrl: `${web_url}`,
},
},
firebase.dynamicLinks.ShortLinkType.UNGUESSABLE,
);
--- By Custom Link ---
longDynamicLink: `${prefix_url}/?link=${link_url}&apn=${package_name}&ibi=${bundle_id}&isi=xxxxxxxxx&ofl=${web_url}`,
suffix: {
option: 'UNGUESSABLE',
},
};
Issue -: Link on desktop browser not working (fallback url not working)
Dynamic link should redirect a website link on desktop

gatsby-plugin-google-analytics + Shopify - Conversions not working

I have a Gatsby site sourcing from Shopify, and I'm having a hard time getting the Acquisition Conversions working.
My guess is that when they go to the Checkout page, since it's on Shopify's domain, it sees that as Direct traffic.
My current configuration is:
{
resolve: `gatsby-plugin-google-analytics`,
options: {
trackingId: "...",
head: true,
anonymize: false,
respectDNT: false,
allowLinker: true,
},
},
I just added that allowLinker in to test today. Is there anything else I'm missing? I'm not too familiar with analytics I'm just a humble javascript farmer.
Thank you
Google Analytics recently changed their API to version 4 and upon other things, they changed the way the tracking identifier is set to the page. I suppose that the plugins will migrate soon to that changes but in the meantime, this is the only plugin available that works with that new API version: gatsby-plugin-google-gtag. So:
// In your gatsby-config.js
module.exports = {
plugins: [
{
resolve: `gatsby-plugin-google-gtag`,
options: {
// You can add multiple tracking ids and a pageview event will be fired for all of them.
trackingIds: [
"GA-TRACKING_ID", // Google Analytics / GA
"AW-CONVERSION_ID", // Google Ads / Adwords / AW
"DC-FLOODIGHT_ID", // Marketing Platform advertising products (Display & Video 360, Search Ads 360, and Campaign Manager)
],
// This object gets passed directly to the gtag config command
// This config will be shared across all trackingIds
gtagConfig: {
optimize_id: "OPT_CONTAINER_ID",
anonymize_ip: true,
cookie_expires: 0,
},
// This object is used for configuration specific to this plugin
pluginConfig: {
// Puts tracking script in the head instead of the body
head: false,
// Setting this parameter is also optional
respectDNT: true,
// Avoids sending pageview hits from custom paths
exclude: ["/preview/**", "/do-not-track/me/too/"],
},
},
},
],
}
All the above parameters are optional, just omit them and replace the GA-TRACKING_ID for your real identifier.
I'm not sure if you ever solved it #cYberSport91, but in the year 2021 AD I am trying to do the same. This is what I found:
Place this snippet in your gatsby-ssr.js or gatsby-browser.js:
exports.onRenderBody = ({ setPostBodyComponents }) => {
const attachCode = `
if (ga) {
ga('require', 'linker');
ga('linker:autoLink', ['destination1.com', 'destination2.com']);
}`
setPostBodyComponents([<script dangerouslySetInnerHTML={{
__html: attachCode
}}/>])
}
Source: Gatsby Git Issues
(Still waiting to confirm with my client whether this solution works)

React Native - How to persist a Firebase authenticated user session from react-native app to a (react-native-webview) webview component?

I have a react-native app which uses Firebase (with "#react-native-firebase/auth": "^6.0.1").
In the app there is one Webview (with "react-native-webview": "^7.5.2").
The user logs in, then I have access to its jwt by using:
auth().currentUser.getIdTokenResult()
.then(jwtToken => {
console.log('jwtToken: ', jwtToken.token);
})
Now I need the user to open the Webview and still being connected because the webview points to my firebase hosting page.
<WebView
source={{
uri: 'my-firebase-hosting-url',
headers: {
Authorization: jwtToken,
},
}}
renderLoading={this.renderLoadingView}
startInLoadingState={true}
sharedCookiesEnabled={true}
thirdPartyCookiesEnabled={true}
domStorageEnabled={true}
ref={ref => {
this.webview = ref;
}}
/>
On the server side, I have setup express and cookie-session.
The user doesn't seems to be logged in the webview: on the server side, when I console.log(req.session) it shows an empty object {}.
I've tried multiple options but nothing seems to work in iOS (not tried on Android yet)
What am I missing? Are there extra steps on the frontend/backend? (I am still new to programming)
Thank you for your help.
I finally solved it and hope it will help others:
Design your state
state = {
shouldRenderWebview: false,
authorization: ''
...
In your constructor, get a refreshed token from firebase
auth()
.currentUser.getIdTokenResult()
.then(result => {
this.setState({
authorization: result.token,
shouldRenderWebview: true,
});
})
Design your main component to either show a loading view (while it's getting the token) or render the webview
Your webview (and add 'Bearer' to the code)
const Authorization = 'Bearer ' + this.state.authorization;
<WebView
source={{
uri: this.state.urlToGo,
headers: {
Authorization,
},
}}
....
In your backend, check if the authentication code is valid
firebase.auth().verifyIdToken(req.headers.authorization.substr(7));
Then do your stuff depending on the result.

Change open graph title dynamically before sharing on Facebook

How do I change open graph title dynamically before sharing on face book?
The code is
FB.ui(
{
method: 'share_open_graph',
action_type: 'og.likes',
action_properties: JSON.stringify({
object: {
'og:url': myurl,
'og:title': mytitle,
'og:description': mydescription,
'og:image': myimageURL,
},
}),
},
function(response) {
console.log(response);
// Action after response
},
);
You canĀ“t, that option was just a workaround that does not work anymore. You must provide correct OG tags in the source of the shared URL.

browser-sync for SPA: how to sync document fragments: #/contact

I'm developing a SPA (Single Page Application) and use grunt-browsers-sync.
All browser-sync features seem to work: CSS injection, scrolling and form synchronization.
It's a SPA so no navigation to other pages in done. Navigation is done via routes in the document fragment (I use the SammyJs library for this)
mysite.com/#/home
mysite.com/#/contact
mysite.com/#/...
It seems BrowserSync doesn't synchronizes document fragments.
I think it's because document fragments are handled by the browser and not requested at the BrowserSync server/proxy.
Is there some way to make the scenario work?
PS: I have a javascript callback when navigating, which I can use to send the new url to BrowserSync at development (if BrowserSync supports something like that)
I also tried using browser-sync for a single-page backbone application.
Routes changes are basically triggered on clicking anchors. Unfortunately, browser-sync doesn't play well with events having stopPropagation & hence, the click wasn't triggered in other browsers and routes were synced.
Since then I've forked and fixed this plus other issues namely event syncing for mouseup, mousedown, keyup, keydown and contenteditable div.
The pull-request is still pending though, so meanwhile you can use browser-sync-client from https://github.com/nitinsurana/browser-sync-client
You'll need to have configuration as follows for the fixes to take effect . Notice the capture, contenteditable, mouseup and other config options not present in browser-sync
var bs = require("browser-sync").create();
var client = require("./");
client["plugin:name"] = "client:script";
bs.use(client);
bs.init({
//server: {
// baseDir: ["test/fixtures"]
//},
proxy: 'http://localhost:8080',
open: false,
minify: false,
snippetOptions: {
rule: {
//match: /SHNAE/,
match: /<\/head>/i,
fn: function (snippet) {
return snippet + "\n</head>";
}
}
},
clientEvents: [
"scroll",
"input:text",
"input:toggles",
"input:keydown",
"input:keypress",
"form:submit",
"form:reset",
"click",
"contenteditable:input",
"mouseup",
"mousedown",
"select:change"
],
ghostMode: {
clicks: true,
scroll: true,
forms: {
submit: true,
inputs: true,
toggles: true,
keypress: true,
keydown: true,
contenteditable: true,
change: true
},
mouseup: true,
mousedown: true
},
capture:true
});

Resources