Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

identifyUser in react and react native on in-app and push notification fail to populate many fields (location, timezone,locale) #13006

Closed
3 tasks done
ericowhadi opened this issue Feb 13, 2024 · 6 comments
Assignees
Labels
Push Notifications Related to Push Notification components question General question

Comments

@ericowhadi
Copy link

Before opening, please confirm:

JavaScript Framework

React, React Native

Amplify APIs

Push Notifications

Amplify Version

v6

Amplify Categories

notifications

Backend

Amplify CLI

Environment information

# Put output below this line
  System:
    OS: macOS 13.6.3
    CPU: (8) arm64 Apple M2
    Memory: 32.64 MB / 8.00 GB
    Shell: 5.9 - /bin/zsh
  Binaries:
    Node: 20.10.0 - /usr/local/bin/node
    Yarn: 1.22.21 - /usr/local/bin/yarn
    npm: 10.2.3 - /usr/local/bin/npm
    Watchman: 2023.12.04.00 - /opt/homebrew/bin/watchman
  Browsers:
    Chrome: 121.0.6167.160
    Safari: 17.2.1
  npmPackages:
    @aws-amplify/auth: ^6.0.10 => 6.0.15 
    @aws-amplify/auth/cognito:  undefined ()
    @aws-amplify/auth/cognito/server:  undefined ()
    @aws-amplify/auth/enable-oauth-listener:  undefined ()
    @aws-amplify/auth/server:  undefined ()
    @aws-amplify/core: ^6.0.10 => 6.0.15 
    @aws-amplify/core/internals/adapter-core:  undefined ()
    @aws-amplify/core/internals/aws-client-utils:  undefined ()
    @aws-amplify/core/internals/aws-client-utils/composers:  undefined ()
    @aws-amplify/core/internals/aws-clients/cognitoIdentity:  undefined ()
    @aws-amplify/core/internals/aws-clients/pinpoint:  undefined ()
    @aws-amplify/core/internals/providers/pinpoint:  undefined ()
    @aws-amplify/core/internals/utils:  undefined ()
    @aws-amplify/core/server:  undefined ()
    @aws-amplify/ui-react: ^6.0.7 => 6.1.1 
    @aws-amplify/ui-react-internal:  undefined ()
    @aws-amplify/ui-react-notifications: ^2.0.9 => 2.0.9 
    @emotion/react: ^11.11.3 => 11.11.3 
    @emotion/styled: ^11.11.0 => 11.11.0 
    @mui/icons-material: ^5.15.9 => 5.15.9 
    @mui/material: ^5.15.9 => 5.15.9 
    @testing-library/jest-dom: ^5.17.0 => 5.17.0 
    @testing-library/react: ^13.4.0 => 13.4.0 
    @testing-library/user-event: ^13.5.0 => 13.5.0 
    aws-amplify: ^6.0.15 => 6.0.15 
    aws-amplify/adapter-core:  undefined ()
    aws-amplify/analytics:  undefined ()
    aws-amplify/analytics/kinesis:  undefined ()
    aws-amplify/analytics/kinesis-firehose:  undefined ()
    aws-amplify/analytics/personalize:  undefined ()
    aws-amplify/analytics/pinpoint:  undefined ()
    aws-amplify/api:  undefined ()
    aws-amplify/api/server:  undefined ()
    aws-amplify/auth:  undefined ()
    aws-amplify/auth/cognito:  undefined ()
    aws-amplify/auth/cognito/server:  undefined ()
    aws-amplify/auth/enable-oauth-listener:  undefined ()
    aws-amplify/auth/server:  undefined ()
    aws-amplify/datastore:  undefined ()
    aws-amplify/in-app-messaging:  undefined ()
    aws-amplify/in-app-messaging/pinpoint:  undefined ()
    aws-amplify/push-notifications:  undefined ()
    aws-amplify/push-notifications/pinpoint:  undefined ()
    aws-amplify/storage:  undefined ()
    aws-amplify/storage/s3:  undefined ()
    aws-amplify/storage/s3/server:  undefined ()
    aws-amplify/storage/server:  undefined ()
    aws-amplify/utils:  undefined ()
    firebase: ^10.8.0 => 10.8.0 
    firebase/analytics:  undefined ()
    firebase/app:  undefined ()
    firebase/app-check:  undefined ()
    firebase/auth:  undefined ()
    firebase/auth/cordova:  undefined ()
    firebase/auth/web-extension:  undefined ()
    firebase/compat:  undefined ()
    firebase/compat/analytics:  undefined ()
    firebase/compat/app:  undefined ()
    firebase/compat/app-check:  undefined ()
    firebase/compat/auth:  undefined ()
    firebase/compat/database:  undefined ()
    firebase/compat/firestore:  undefined ()
    firebase/compat/functions:  undefined ()
    firebase/compat/installations:  undefined ()
    firebase/compat/messaging:  undefined ()
    firebase/compat/performance:  undefined ()
    firebase/compat/remote-config:  undefined ()
    firebase/compat/storage:  undefined ()
    firebase/database:  undefined ()
    firebase/firestore:  undefined ()
    firebase/firestore/lite:  undefined ()
    firebase/functions:  undefined ()
    firebase/installations:  undefined ()
    firebase/messaging:  undefined ()
    firebase/messaging/sw:  undefined ()
    firebase/performance:  undefined ()
    firebase/remote-config:  undefined ()
    firebase/storage:  undefined ()
    react: ^18.2.0 => 18.2.0 
    react-dom: ^18.2.0 => 18.2.0 
    react-hot-toast: ^2.4.1 => 2.4.1 
    react-scripts: 5.0.1 => 5.0.1 
    uuid: ^9.0.1 => 9.0.1 (8.3.2)
    web-vitals: ^2.1.4 => 2.1.4 
  npmGlobalPackages:
    @aws-amplify/cli: 12.10.0
    http-server: 14.1.1

Describe the bug

I am using both in-app and push notification on a react native and a react webapp. Of course the push notification on react web app is not don eusing amplify since it is not supported, but I wired it manually using firebase and a lamda that proxy a call to pinpoint updateEndpoint API.
When using the api of updateUser from aws-amplify/in-app-messaging or from aws-amplify/push-notifications both api even if returning success, fail to internally update pinpoint fields that a direct call to pinpoint updateEndpoint API successfully update. These fields are:
demographic.locale
demographic.timezone
location.latitude
location.longitude
location.city
location.country
location.postalCode
location.region

Expected behavior

All these field should be correctly populating the Pinpoint internal database. Else not campaign targeting these field will work

Reproduction steps

follow direction to install and configure ether amplify push notification on react native, or in-app notifications in ether react or react-native.
Then, invoke identifyUser in ether in-app or push-notifications.
make sure you populate the demographic and location that are reported buggy.
And then go to pinpoint console, segment, export segment. THen look at the excelsheet, and see that all the boggus fields are indeed blank. I have verified that directly invoking pinpoint updateEndpoint API , I correctly populate these fields and they do show up on the exported endpoints collected as mentioned above via pinpoint console.

Code Snippet

// Put your code below this line.

mport React , {useState,useEffect} from 'react';
import {fetchUserAttributes} from '@aws-amplify/auth'
import { Authenticator, useAuthenticator} from '@aws-amplify/ui-react';
import '@aws-amplify/ui-react/styles.css';
import {syncMessages, identifyUser} from 'aws-amplify/in-app-messaging'
import {withInAppMessaging} from '@aws-amplify/ui-react-notifications'
import Dashboard from './dashboard/Dashboard.js'
import Notification from './components/Notification'
import {v4 as uuidv4} from 'uuid'
import {generateClient} from 'aws-amplify/api'
import {pinpointGateway} from "./graphql/mutations"

const client = generateClient()

function App() {
  const { user } = useAuthenticator((context) => [context.user]);
  const { route } = useAuthenticator((context) => [context.route]);


  console.log("user",user)
  console.log("route", route)


  const [userDetails, setUserDetails] = useState(null);
  const [errorMessage, setErrorMessage] = useState(null)
  const [pushToken, setPushToken] = useState(null)

  useEffect(() => {
    const params = new URLSearchParams(window.location.search);
    const errorDescription = params.get('error_description');
    if (errorDescription) {
      setErrorMessage(errorDescription.startsWith("PreSignUp failed with error . ")?errorDescription.substring(30):errorDescription);
    }
 
  }, []);



  useEffect(() => {
    const fetchUserDetails = async () => {
      try {
        const userData = await fetchUserAttributes();
        setUserDetails(userData);

        // Now userDetails contains more detailed information
      } catch (error) {
        console.error('Error fetching user details', error);
      }
    };

    if (route === "authenticated") fetchUserDetails();
    else setUserDetails(null)
  }, [route]);

  useEffect(()=>{
  const identifyUserInput = async () => {
    let location = {}
    if (navigator.geolocation){
      navigator.geolocation.getCurrentPosition((position)=>{
        location = {latitude: position.coords.latitude,
        longitude: position.coords.longitude
        }
      }, (error)=>{
        console.log("Location permission denied")
      })
    } else{
      console.log("Geolocation is not supported by this browser.")
    }
    return {
    userId: userDetails.sub,
    userProfile: {
      email: userDetails.email,
      name: userDetails.name,
      plan:'myplan',
      customProperties:{
        hobbies: ["paintball", "bridge"] //~~EO todo
      }
  },
  demographic:{
    appVersion: "1.0.0",
    locale: navigator.language.replace("-","_"), //~~EO todo add what we support as filter
    make: navigator.vendor,
    model: navigator.appCodeName,
    modelVersion: navigator.appVersion.substring(0,50),
    platform: navigator.platform,
    platformVersion: "",
    timezone: Intl.DateTimeFormat().resolvedOptions().timeZone

  },
  location: {
    latitude: 10.12345,//location.latitude,
    longitude: -2.12345,//location.longitude,
    city: "Tomball",
    country:"US",
    postalCode:"77377",
    region:"TEXAS",


  },
  metrics:{
    // you app specific metrics  todo
  },
  options:{
    address: userDetails.email, //E.g. A device token or email address
    optOut:"NONE", //Either ALL or NONE
    userAttributes: {
      interests: ['belotte','rami']
    }
  }
  }
  } 

  const dealWithPushNotification = async ()=>{

    const identifiedUserInput =await identifyUserInput()
    console.log("identified user:",identifiedUserInput)
    await identifyUser(identifiedUserInput)

      if (pushToken !== 'error') {

        
        const res= await client.graphql({
          query: pinpointGateway,
          variables:{
            functionName: "updateEndpoint",
            functionParams:JSON.stringify(
              {EndpointId: "test",
              EndpointRequest:{

              Demographic:{
                AppVersion: identifiedUserInput.demographic.appVersion,
                Locale: identifiedUserInput.demographic.locale,
                Make: identifiedUserInput.demographic.make,
                Model: identifiedUserInput.demographic.model,
                ModelVersion: identifiedUserInput.demographic.modelVersion,
                Platform: identifiedUserInput.demographic.platform,
                PlatformVersion: identifiedUserInput.demographic.platformVersion,
                Timezone: identifiedUserInput.demographic.timezone
            
              },
              Location: {
                Latitude: identifiedUserInput.location.latitude,
                Longitude: identifiedUserInput.location.longitude,
                City: identifiedUserInput.location.city,
                Country:identifiedUserInput.location.country,
                PostalCode:identifiedUserInput.location.postalCode,
                Region:identifiedUserInput.location.region,
            
            
              },
              Metrics: identifiedUserInput.metrics,
              Address: pushToken,
              OptOut: "NONE",
              Attributes: {
                  email:[identifiedUserInput.userProfile.email],
                  name: [identifiedUserInput.userProfile.name],
                  plan: [identifiedUserInput.userProfile.plan],
                  ...identifiedUserInput.userProfile.customProperties

              },
              User:{
                UserId: identifiedUserInput.userId,
                UserAttributes: identifiedUserInput.options.userAttributes
                
              },
              RequestId: uuidv4()

            }
          })
          },
          authMode: "iam"
        })
        console.log(res)

      }
      
      syncMessages()
      console.log("DONE")

  }

  if (userDetails && pushToken) dealWithPushNotification()

},[userDetails,pushToken])

  const clearErrorAndRefresh = () => {
    window.location.href = window.location.pathname;
  };

    // If there is an error, display a separate UI
    if (errorMessage) {
      return (
        <div style={{display:"flex", justifyContent:"center", alignItems:"center", height:"100vh", width:"100vw"}}>
        <div className="amplify-flex amplify-alert amplify-alert--error" role="alert" style={{width:"450px", backgroundColor:"#fce9e9"}}>
          <span className="amplify-alert__icon">
            <span className="amplify-icon" aria-hidden="true" style={{width: "1em", height: "1em"}}>
              <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M12 2C6.48 2 2 6.48 2 12C2 17.52 6.48 22 12 22C17.52 22 22 17.52 22 12C22 6.48 17.52 2 12 2ZM13 17H11V15H13V17ZM13 13H11V7H13V13Z" fill="currentColor">
                </path>
              </svg>
            </span>
          </span>
          <div style={{flex: "1 1 0%"}}>
            <div className="amplify-alert__body">{errorMessage}</div>
          </div>
          <button aria-label="Dismiss alert" className="amplify-button amplify-field-group__control amplify-button--link amplify-alert__dismiss" type="button" onClick={clearErrorAndRefresh} >
          <span className="amplify-icon" aria-hidden="true" style={{width: "1em",height: "1em"}}>
            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M19 6.41L17.59 5L12 10.59L6.41 5L5 6.41L10.59 12L5 17.59L6.41 19L12 13.41L17.59 19L19 17.59L13.41 12L19 6.41Z" fill="currentColor"></path>
            </svg>
          </span>
          </button>
        </div>
        </div>
      );
    }

  return (
    <Authenticator>
       
      {({ signOut, user }) => {
        console.log("user",user)
        console.log("userDetails",userDetails)
        return (<>
          <Notification pushTokenCallback={setPushToken}/>
          <Dashboard signOut={signOut} user={user}/>
      </>)}}
    </Authenticator>
  );
}

export default withInAppMessaging(App);



### Log output

<details>

// Put your logs below this line


</details>


### aws-exports.js

_No response_

### Manual configuration

_No response_

### Additional configuration

_No response_

### Mobile Device

_No response_

### Mobile Operating System

_No response_

### Mobile Browser

_No response_

### Mobile Browser Version

_No response_

### Additional information and screenshots

_No response_
@ericowhadi ericowhadi added the pending-triage Issue is pending triage label Feb 13, 2024
@nadetastic nadetastic added the Push Notifications Related to Push Notification components label Feb 13, 2024
@cwomack cwomack self-assigned this Feb 13, 2024
@cwomack
Copy link
Member

cwomack commented Feb 13, 2024

Hello, @ericowhadi and sorry to hear your'e running into this. Can you clarify if this is being experienced with Apple Push Notification service (APNs), Firebase Cloud Messaging (FCM), or both? Also, can you double check that the required credentials have been input for your desired service channel within the Pinpoint console? Should be able to verify this under the project > Configure features > Push Notifications > service provider.

@cwomack cwomack added question General question investigating This issue is being investigated pending-response and removed pending-triage Issue is pending triage labels Feb 13, 2024
@ericowhadi
Copy link
Author

the issue exist on both APNs and FCM and on in-app messaging (both react native and react).
The credentials are OK and correct, as all other information provided in identifyUser are making it correctly to pinpoint. only all location info, plus locale and timezone from demographic are not transmitted.

@ericowhadi
Copy link
Author

note that for APN, I have not yet enabled APNs backend, but the identifyUser workflow is independent of the push notification service provider. Service provider is important to receive the token, and then the identify user update the pinpoint Endpoint with the token in the address field. on Apple, because I don't yet have my DUNS number to create a valid apple developper account that can enable the APN service I have not tested really end to end. However, I know it fails because calling the IdentifyUser with a fake token does correctly update the Endpoint with the fake token, along with many other attributes, except the failed ones.

@ericowhadi
Copy link
Author

update, actually, after more testing, it is more than I previously said. All the demographic values are wrong (not populated). I saw that looking at android push notification from both emulator and real device pixel 7, none of the data about demographics gets updated, and for both device I am getting the same values in pinpoint: Default values:
Demographic.ModelVersion: 34
Demographic.AppVersion: android/34
Demographic.Platform: android

@Samaritan1011001
Copy link
Member

Hi @ericowhadi, thanks for providing the code snippet. I notice that the demographic, metrics and location object blocks are outside the userProfile block in your identifyUserInput. Can you move inside and see if you still face the problem?

It should be as shown in the docs: https://docs.amplify.aws/javascript/build-a-backend/more-features/in-app-messaging/identify-user/

For a quick review:

const identifyUserInput = {
  userId: '', // E.g. user-id
  userProfile: {
    email: '', // E.g. [email protected]
    name: '', // E.g. name-of-the-user
    plan: '' // E.g. plan-they-subscribe-to
    customProperties: {
      // E.g. hobbies: ['cooking', 'knitting'],
    },
    demographic: {
      appVersion: '',
      locale: '', // E.g. en_US
      make: '', // E.g. Apple
      model: '', // E.g. iPhone
      modelVersion: '', // E.g. 13
      platform: '', // E.g. iOS
      platformVersion: '', // E.g. 15
      timezone: '' // E.g. Americas/Los_Angeles
    },
    location: {
      city: '', // E.g. Seattle
      country: '', // E.g. US,
      postalCode: '', // E.g. 98121
      region: '', // E.g. WA
      latitude: 0.0,
      longitude: 0.0
    },
    metrics: {
      // E.g. logins: 157
    },
  },
};

@ericowhadi
Copy link
Author

@Samaritan1011001 oops, my bad, I should be more careful following the docs. Sorry again, and thanks for catching my mistake.
After correcting it everything works as expected.

@cwomack cwomack removed the investigating This issue is being investigated label Mar 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Push Notifications Related to Push Notification components question General question
Projects
None yet
Development

No branches or pull requests

4 participants