Open chrisdrackett opened 4 years ago
Oh interesting! I didn't know window
acted like this in React Native.
Does https://github.com/DavidWells/analytics/pull/44 solve this issue for you when testing locally?
Looks like the code trips up here with the different navigator in RN https://github.com/DavidWells/analytics/blob/cca3bafda3f902dc6da484ec3d6245ccb6d12fe0/packages/analytics-core/src/utils/getOSName/browser.js#L5
I just did another pass in #44. I haven't tested it all out yet, but for the most part react native should act like the server implementation. For now I'm just getting my feet wet understanding the code. #44 is probably more heavy handed than it could be (there are things that can be done in React Native to get a lot of the stuff that isn't available in node.js) but for now I'd like to get things working first and foremost. I'll be spending more time on this tomorrow!
I'm wondering if we can do something like https://github.com/react-native-community/react-native-device-info/blob/master/src/web/index.js#L87-L106 to populate the correct info on react native. I haven't used react native in a while and I'm not sure whats possible.
I found this to check if we are running in RN context
if (typeof document != 'undefined') {
// I'm on the web!
}
else if (typeof navigator != 'undefined' && navigator.product == 'ReactNative') {
// I'm in react-native
}
else {
// I'm in node js
}
I'm not 100% on if it works or not 😅
I'm pretty sure this works and is where I started, but I didn't realize how much document
was used in others parts of the lib! This is why I went down my current route, but I'm not sure if that is the best way forward either :D
I think there are probably two levels of RN support:
2 would be super cool, but would require using react native code like Platform and I'm not sure yet the best way to go about this.
I wonder if the best way to handle 2 is to have a way to plop things like platform, viewport size, etc. into the config and then just have react native users (via a package or by hand) throw those values in when initializing analytics
- just get React Native working (probably making it look like a server)
- actually add rich react-native support (fill out things like platform, width, height, etc.)
This sounds good to me 😃. I love the idea of RN support!
For # 2, We might need to set up another build to target react native... All in good time 😅
Does React native use any DOM APIs? If not, we might be able to simply add the react-native check to the isBrowser util then we wouldn't need to check both everywhere
yep! this is exactly what I did :)
as far as I can tell the issue now is that React Native is trying to use the browser version of plugins, which won't work as RN has no document or normal Dom for that matter: https://github.com/DavidWells/analytics/blob/master/packages/analytics-plugin-segment/src/browser.js#L118
I managed to spin up https://github.com/expo/create-react-native-app & test it out.
I see what you are saying, it appears react native is loading the browser version not the serverside implementation.
Everything work just work â„¢, if the analytics.es.js (serverside implementation) would load.
... This is perplexing.
I believe it has something to do with this mapping in package.json
https://github.com/DavidWells/analytics/blob/master/packages/analytics-core/package.json#L28-L31
As you mentioned, this will affect all the plugins as well. We need to figure out a way to solve this so the serverside implementations are used when folks are running in React Native.
1 possible solution is publishing different modules for client + server implementations but I'd like to avoid this because of the additional maintenance burden.
In the meantime, as this gets resolved for the serverside plugins, you can inline your plugins & make API calls to remote analytics tools like this:
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Analytics from 'analytics'
const analytics = Analytics({
app: 'coolbeans',
plugins: [{
name: 'inlined-thing',
page: ({ payload }) => {
// make your remote call
console.log('page payload', payload)
},
track: ({ payload }) => {
// make your remote call
console.log('track payload', payload)
}
}]
})
export default function App() {
console.log(analytics.getState())
setTimeout(() => {
analytics.page()
analytics.track('thing', {
color: 'blue'
})
}, 300)
return (
<View style={styles.container}>
<Text>Hi cool stuff</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Are you guys working on this or one should just work as suggested above with a serverside plugin?
Hey @gafner, I'm still trying to figure out how React-native resolves it's modules.
By default, it's loading the browser version of the analytics library and the browser version of plugins.
Do you know if there is a specific package.json
field for the react-native bundler to use?
Are you guys working on this or one should just work as suggested above with a serverside plugin?
The above code should work for you in React-native. However, If you include @analytics/google-analytics
for example, it will attempt to load the browser version instead of the node serverside version of the package
How are you guys planning to support multiple storage ways? Like cookies
, AsyncStorage
or any other native storage? Is it a problem for the plugin land? Or is this something that analytics will handle?
@jgcmarins Do cookies work in React Native? If yes, then they are already in use there 😃
Under the hood, analytics tries to use these 3 mechanisms in this order:
https://github.com/DavidWells/analytics/blob/master/packages/analytics-util-storage/src/index.js
It's possible that we could expose this as an option where any method could be used like AsyncStorage
.
I'm looking for React Native experts to help out here as I have little experience working with it myself. 😃
@DavidWells This lib is a good one and would solve many react-native problems. We currently use GA for firebase and there are many differences mainly in the reports.
@chrisdrackett i forked the react-native-google-analytics and adjust to send metrics. The firebase report is very different and you can see web report with this lib. it worked well for me. You can see here and install like this:
"react-native-google-analytics": "https://github.com/fernando-pascoal/react-native-google-analytics.git"
Is this still actively being looked at? I just hit this problem with our React native app, thinking I could use this library but it seems to be looking for a window.location
object, which of course doens't exist so the app crashes. Could we not just have a config property to enforce server side tracking rather than relying on detection that seems to not work?
ie
const analytics = analyics({
app: "some-app",
client: "server",
plugins: [
googleAnalytics({
trackingId: "xxxx",
}),
],
});```
Hello folks, i'm trying to add a GA4 plugin for react-native but i receiving this error:
do you guys have plans to add extra verifications to work in mobile apps?
@johnsoncwb did you manage to work around this error and get it running?
Possibly fixed via https://github.com/DavidWells/analytics/pull/367 released with analytics@0.8.7
Currently if you run this in a react native project you get the following error:
TypeError: undefined is not an object (evaluating 'os.indexOf')
I'm guessing that the check to see if this is running in a browser is passing even though react native should probably be treated like a "server" like environment.