Hi team, we are trying to integrate rudderstack wi...
# general
b
Hi team, we are trying to integrate rudderstack with iOS and send the data to GA4, I get the error
"error": "ga4AppInstanceId must be provided under externalId"
I checked into documentation https://www.rudderstack.com/docs/destinations/streaming-destinations/google-analytics-4/setting-up-google-analytics-4-in-rudderstack/ and found
Enter the identifier which RudderStack should look for in the payload and map to the GA4
Does this mean we can map a unique id from rudderstack payload to be client id for GA4? What would be the best way to set this? what we want to do is send data from each app platform to it's own GA4 destination based on different env like dev, uat, prod.
b
hi @boundless-notebook-34527 this is an error for firebase client which expects an
ga4AppInstanceId
inside
externalId
of our rudderstack payload because rudderstack maps
ga4AppInstanceId
to
app_instance_id
which is required to make a call to ga4 while the doc you are referring to is ga4 client_Id. where you can specify from which place in your payload you want to send ga4 client_id and rudderstack will take from there and sent it to ga4.
b
@bulky-breakfast-19942 Thank you for the prompt response. I am still having problem in trying to piece together the setup. Please let me know if any of my assumption is wrong. 1. I need to set
GA4 client_id Field Identifier
in destination config, I am assuming this is keyName and not value right? Then I need to send the
ga4AppInstanceId
which is probably
GOOGLE_APP_ID
that we get from GA4 dashboard right? So, for the code below
Copy code
let option = RSOption()
        option.putExternalId("ga4AppInstanceId", withId: "GOOGLE_APP_ID")
        RSClient.sharedInstance().track(event.description, properties: eventProperties, option: option)
GA4 client_id Field Identifier
should be set to
ga4AppInstanceId
and not
GOOGLE_APP_ID
right? I tried this but I did not see
externalId
or
ga4AppInstanceId
when testing on live events on source and I am still getting same error as before in destination live events https://www.rudderstack.com/docs/destinations/streaming-destinations/google-analytics-4/google-analytics-4-cloud-mode/#mapping-client_id This documentation states that even if we do not set
GA4 client_id Field Identifier
it will map
anonymousId
to
client_id
our payload has
anonymousId
but still we are getting error
b
i am sending you a sample ga4 payload where we are sending both
ga4AppInstanceId
and
client_id
. you can reference that
Copy code
{
  "channel": "web",
  "messageId": "ec5481b6-a926-4d2e-b293-0b3a77c4d3be",
  "anonymousId": "ea5cfab2-3961-4d8a-8187-3d1858c99090",
  "context": {
    "app": {
      "build": "1.0.0",
      "name": "RudderLabs JavaScript SDK",
      "namespace": "com.rudderlabs.javascript",
      "version": "1.0.0"
    },
    "device": {
      "adTrackingEnabled": "false",
      "advertisingId": "T0T0T072-5e28-45a1-9eda-ce22a3e36d1a",
      "id": "3f034872-5e28-45a1-9eda-ce22a3e36d1a",
      "manufacturer": "Google",
      "model": "AOSP on IA Emulator",
      "name": "generic_x86_arm",
      "type": "ios",
      "attTrackingStatus": 3
    },
    "ip": "0.0.0.0",
    "library": {
      "name": "RudderLabs JavaScript SDK",
      "version": "1.0.0"
    },
    "locale": "en-US",
    "os": {
      "name": "iOS",
      "version": "14.4.1"
    },
    "screen": {
      "density": 2
    },
    "externalId": [
      {
        "type": "ga4AppInstanceId",
        "id": "************"
      }
    ],
    "userAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36"
  },
  "type": "track",
  "event": "product added",
  "properties": {
    "currency": "USD",
    "price": 2.4,
    "quantity": 2,
    "client_id": "<tel:123456.7654321|123456.7654321>",
    "products": [
      {
        "product_id": "507f1f77bcf86cd799439011",
        "name": "Monopoly: 3rd Edition",
        "coupon": "SUMMER_FUN",
        "category": "Apparel",
        "brand": "Google",
        "variant": "green",
        "price": "19",
        "quantity": "2",
        "position": "1",
        "affiliation": "Google Merchandise Store",
        "currency": "USD",
        "discount": 2.22,
        "item_category2": "Adult",
        "item_category3": "Shirts",
        "item_category4": "Crew",
        "item_category5": "Short sleeve",
        "item_list_id": "related_products",
        "item_list_name": "Related Products",
        "location_id": "L_12345"
      }
    ]
  },
  "integrations": {
    "All": true
  }
}
if you see above payload i am sending
ga4AppInstanceId
from
externalId
and
client_id
is coming from properties which i configured on dashboard.
GA4 client_id Field Identifier
=
properties.client_id
👍 1
b
Oh thanks, this is now lot clearer,
ga4AppInstanceId
from
externalId
is mapped onto
app_instance_id
of GA4 payload and
GA4 client_id Field Identifier
is a different field definition for sending out
client_id
to GA4 event param field
client_id
👍 1
@bulky-breakfast-19942 Please do let me know if it's better to create new thread or ask on general channel than tagging you because I'm not sure if there is a team or oncall system for the support here. We just discovered that despite the events being present in the GA4 destination from rudderstack side, we do not see it in our GA4 dashboard. We actually get native GA4 events instead, we have firebase setup in native app as well and I think analytics is getting auto-tracked. Do we need to disable the analytics from GA4 client library on native app? We checked the secret and app id as well, it seems fine. We are not sure if there is some setup we are failing on our side.
I want to also add few info here, we only send
ga4AppInstanceId
by fetching it using Firebase/Analytics framework for getting appInstanceId and we do not send
client_id
at the moment.
b
can you check in your configuration if
Enable debug mode
option is enabled or not?
b
You probably mean this on Rudderstack config right? It is enabled.
b
yes, that's why you are not seeing it in realtime dashboard enable debug mode just validates your events you need to disable it
b
@bulky-breakfast-19942 I got it working after doing as you suggested. Thank you again 🙏. One more issue that we see is screen tracking events are not seen at destination as well as GA4, it's using native SDK tracking, are these settings in config responsible for it? Or maybe there is something else we could be missing?
b
for native sdk , you have different ga4 destination which is in device mode right?
b
I think we are using cloud mode at the moment, I think it was mentioned here https://www.rudderstack.com/docs/destinations/streaming-destinations/google-analytics-4/setting-up-google-analytics-4-in-rudderstack/ for mobile it only supports cloud mode. Actually for ga4 sdk (Firebase/Analytocs) we have not implemented any specific tracking in app but we have firebase setup in iOS, we are fetching appinstance id from firebase/analytics package and I think it automatically tracks the events after invoking FirebaseApp.configure() Should we diisable app side tracking in some way to allow rudderstack events to go through or can we override the screen tracking events from rudderstack? Or maybe both?
b
you can try both, are you firing
rudderanalytics.track()
events
b
Yes , we are firing that and we can see the events coming to source, just destination is missing it, no error shown as well, just events missing
b
actually sdk events will not be visible in events tab since it's fired by sdk. can you check in ga4 realtime dashboard if events are coming or not??
b
Oh I did not mean sdk event I meant screen events from rudderstack, so currently we see only track events in ga4 destination but not the screen events, screen events only show up in source area
b
actually ga4 cloud mode is not supporting screen events, you need to send screen event as track event only
b
Oh that makes it clear thank you so much, can we use regular google analytics setup not ga4 to get screen tracking there?
Or can transformation function in rudderstack help us to convert screen events to track events?
b
yes can do that or you can send screen event payload in track event and it will work
b
We decided to write transformation instead because screen events have more context information right? We can use it for other data destination like databricks or other DBs
👍 1
@bulky-breakfast-19942 The transformation we apply will transform data before it is sent to GA4 right? I am trying to use this transform script
Copy code
export function transformEvent(event, metadata) {
    if(event["type"] == "screen") { 
        let screen_name = event.event;
        event.properties = {
            "screen_name": event["event"]
        }
        event["event"] = "screen_view";
        event["type"] = "track";
    }
    return event;
}
to convert the screen event to track event for GA4 but I still do not see any info on destination
Or should we do transform on GA4 json structure?
b
i am not sure about that, you can try and test it out and then let me know if it's still not working
👌 1
b
I looked into docs and all examples point to transforming source data so, I guess the destination transformation is done after the transformed source data is sent downstream. For my above example I get this error from GA4 destination side
On the example json we were able to convert
type
from "screen" to "track",
event
from "screen_name" to "screen_view" (custom type) and push event name inside property of track, on the diff it looks same as a new track event but hard to say if this is sufficient
b
basically if you see ga4 docs then all the events are track only. event login, sign_up these all ga4 is considering as track only so i believe you can send screen as track events
b
Maybe it is screen_view as event name then, let me try different combinations and update
b
yes
🙌 1
b
Yes, I fixed it, it was the problem, thank you again, things seem to be working now
b
great
🙌 1
b
@bulky-breakfast-19942 Hi Mihir, we launched our rudderstack implementation this week and opened the experiment this morning, we found that right now out of 58 events 38 events have failed that is 65% of events on the sample failed event we see it's a timestamp issue, could you please help us fix this? We do not add timestamp from our client side so, maybe it is some of config that we are doing in wrong way?
b
can you share sample payload ?
b
Copy code
{
  "type": "track",
  "event": "button_tap",
  "sentAt": "2566-03-03T04:59:44.467Z",
  "channel": "mobile",
  "context": {
    "os": {
      "name": "iOS",
      "version": "16.3.1"
    },
    "app": {
      "name": "Pi Financial",
      "build": "548",
      "version": "1.2.3",
      "namespace": "th.co.cgsec.pi-financial"
    },
    "device": {
      "id": "473477E0-AFE9-4598-810A-3D562B134A34",
      "name": "iPhone",
      "type": "ios",
      "model": "iPhone11,2",
      "manufacturer": "Apple"
    },
    "locale": "en-TH",
    "screen": {
      "width": 375,
      "height": 812,
      "density": 3
    },
    "traits": {
      "anonymousId": "e0f6dd0a-f37c-4a14-97c3-62cb7ad3fada"
    },
    "library": {
      "name": "rudder-ios-library",
      "version": "2.0.1"
    },
    "network": {
      "wifi": false,
      "carrier": "unavailable",
      "cellular": true,
      "bluetooth": false
    },
    "timezone": "Asia/Bangkok",
    "externalId": [
      {
        "id": "D447F9CF5F8D47C785CC63C3A7",
        "type": "ga4AppInstanceId"
      }
    ]
  },
  "rudderId": "f7467c63-eff6-41b0-8592-17e7944e4642",
  "messageId": "1677819577-51fb39a7-f546-41dc-895a-c15adbd3e855",
  "timestamp": "2023-03-03T04:59:38.974Z",
  "properties": {
    "button_name": "resend_otp",
    "screen_name": "2fa_mobile"
  },
  "receivedAt": "2023-03-03T04:59:45.761Z",
  "request_ip": "49.237.19.91",
  "anonymousId": "e0f6dd0a-f37c-4a14-97c3-62cb7ad3fada",
  "integrations": {
    "All": true
  },
  "originalTimestamp": "2566-03-03T04:59:37.680Z"
}
On live event from destination side we notice that some events were in source format for the failed ones but successfully converted to GA4 format for the successful ones, I'm not sure if this info is for any significance
b
if you do not want to send timestamp then remove all of this :
originalTimestamp, sentAt, timestamp
else make sure that all this time stamp is not in future
or alternative could be just send anyone of above 3 and make sure that it's present one
👌 1
b
Actually these values are autoset from mobile SDK but as you suggested for now we can try to update these from latest server time in transformation maybe
👍 1