GA4 Conversion tracking using Measurement Protocol - google-analytics-api

[Edited. Added code sample and more explanations]
Is anybody familiar with the GA4 Measurement Protocol?
We are sending events from our backend servers to the server-side GTM container using the GA4 Measurement Protocol. Everything works fine except for conversion tracking. The events marked as conversion are not counted as conversions if we send those via MP (except for the default "purchase" event, it works perfectly). The same event with the same parameters counts as a conversion if we send it from the browser (client-side GTM). As I couldn't find anything about this issue online, the only thing left was to debug parameter by parameter using the server-side GTM preview mode. Here I discovered, that if I send events from the browser, the requests for events I mark as conversions in GA have "&_c=1" in their query string.
That means, as far as I understand it, that in order to get conversion events via MP, the event request needs to have "_c" query string parameter. I tried adding "_c" as an event param, but that didn't work. Is there a designated JSON parameter to mark the event as a conversion?
------------MORE INFO--------------
Here is an example of an event "Experts". This event gets sent from both the client-side and the server. As you can see in the screenshot, this event is marked as a conversion.
As you can see on the second screenshot, the actual events (137) are much more than the conversions detected (48). The difference are exactly the ones sent from the server-side.
Here is the request body of the server call:
{
"client_id":"Z9TLWnyVC2UK4UssPIVk8J+2n5BZhgWLtWSlFYYSwlg=.1642076344",
"user_id":"119412",
"events": [{
"name": "Experts",
"params": {
"tenweb_action": "[Test action]",
"tenweb_info": "[Some more info]",
"debug_mode":1,
"page_location": "https://10web.io/[some-test-page]"
}
}]
}

#Jan, #DaImTo, and everyone else that might have this issue in the future.
I think I've found a solution. Although it's unofficial and might break at any moment, it's the best one I've found so far. Here is what I ended up doing. While debugging via GTM preview mode I noticed, that in Event Data tab of conversion events there is an object "x-ga-system_properties", that, among other system variables, contains c:"1" . So I tried adding
"x-ga-system_properties":{"c":"1"}
to the event parameters JSON that we send to the Measurement Protocol endpoint of our server-side GTM.
IT WORKED. The events sent that way were registered as conversions by GA4.
Would be great to hear your thoughts on this. Do you think it's a stable solution? Do you think there will be official documentation on this from Google?

Related

How to properly send event parameters with Facebook Server Events

I am setting Facebook Pixel for the first time with the Conversions API and all my TestEvents are correct and I am receiving the events I am supposed to. But in every event under "Overview" I have this error:
No event parameters were detected. Use Test events to view the parameters of an individual event trigger.
I am new to this so I don't even know if this is an error or if it should work like that.
I am having a similar problem.
I am sending Custom Events. The Pixel and Server events are successfully deduplicating. Custom parameters are within both tags, however while the custom parameters are successfully being sent (& are hence visible in Events Manager Test Events) by the Pixel tags, the custom parameters are missing when viewing the Server Events in Test Events.
I have used both Custom HTML tags originally, and now the Facebook tag template, but and have endlessly tweaked the settings, but just cannot resolve this.
Let me know if you made progress!
Here are some good links that may help you
https://www.simoahava.com/analytics/facebook-conversions-api-gtm-server-side-tagging/
https://www.simoahava.com/custom-templates/facebook-pixel/
https://www.optimizesmart.com/gtm-server-side-tagging-for-facebook/

Is there a way to define input context for a Google Action with the Actions SDK?

In the DialogFlow console, you can set an input and output context for an intent.
I would like to have the same functionality using the Actions SDK.
Since I can set the context in my fullfilment webhook in the code, the output SDK is covered.
However, how do I set the input context for an intent to only trigger if that context was fetched?
I could not find this in the documentation examples.
I don't believe you can in the same way, which is part of why they added Dialogflow.
Although as part of your response you can indicate the ExpectedInput for the next Intent, the documentation for the ExpectedIntent makes it clear that your Intents are only used for speech biasing - you'll always get the built-in TEXT Intent.
In fact, this documentation says that you'll only get custom Intents for the initial call - later Intents are always triggered with a built-in one.
Update: One thing you can do is to include information in the response that will be sent back to you in the next request.
If you're using the JavaScript SDK, this is done with the second parameter to ask() and is available via the getDialogState() function.
If you're sending back JSON, this is done using the conversationToken attribute and is available in conversation.conversationToken in the request object you're sent the next round.

How to receive cumulocity real time notifications with SmartREST?

We use the cumulocity REST API. Regular real time notifications work, e.g. we subscribe to /alarms/*, start our connection/polling loop and when we create an alarm we receive the expected JSON. We did not install any specific modules or statements, it just works.
But when we try to do the same with SmartREST we receive this error, as soon as the alarm is created:
40,,/alarms/177649296,Could not find any templates subscribed for the channel
Following the reference guide (http://cumulocity.com/guides/reference/smartrest/) we tried it like this, where all requests have the same X-Id-header and all requests result in the expected http status 200 and no error messages, except for the last one:
Register a smart response template by doing a POST to /s
Body: 11,102,,,$.channel
Handhake: POST to /cep/realtime
Body: 80
Response is our clientId (e.g. 191het1z38bp7iq1m96jqqt8jnef)
Subscribe: POST to /cep/realtime
Body: 81,191het1z38bp7iq1m96jqqt8jnef,/alarms/*
Connect: POST to /cep/realtime
Body: 83,191het1z38bp7iq1m96jqqt8jnef
In the normal REST case the notification consists of a JSON array with 2 elements, both of which have a property "channel". So that is what we would expect from our response template. Instead, we get the aforementioned error 40.
Is our response template wrong? Is it not properly matched by the X-Id? What does it mean, that there are no "templates subscribed for the channel"? The subscriptions are done for a clientId, and not for a specific response template, and the templates are supposed to be matched automatically anyway. So probably "template" means "X-Id" here? The documentation seems ambiguous as to the meaning of that word. But anyway, we did use the same X-Id header in all of the requests.
Any pointer about what we're doing wrong would be appreciated, since we tried pretty much anything by now.
The SmartREST protocol was developed for a IoT-device <-> platform communication. So there was never any design around using it to subscribing to realtime data (except of course for the operations a device needs) as usually devices to not need subscribe to the data that they created themselves.
That said it is possible to use it but with a couple of limitations. Your approach is basically correct but there is one problem with the subscription. The wildcard subscriptions will not work with SmartREST because on subscription it links your X-Id with the channel you subscribed to but there is never a message published on the channel /alarms/*. Thus this kind of weird error message that said that there was no template subscribed for the channel the alarm appeared on. Inside CometD you still receive the alarm because of the wildcard subscription but the SmartREST part does not work.
The messages are published on the channel with the deviceId (e.g. /alarms/12345).
If you subscribe to /alarms/12345 it will work. You can of course subscribe to as many channels as you want but wildcard subscription won't work.
Regarding the templates you need to know the following. The SmartREST parsing is not done on the raw JSON of CometD but on the payload inside it (e.g. the alarm). So a template for an alarm could look like this:
11,500,,$.severity,$.id,$.type,$.severity
This would trigger only if the object has a severity and would return id, type and severity.

How to use standard events in the react native Facebook SDK

The Facebook SDK has the ability to record both custom events and standard events. The standard events are things like "Purchases" "Add to cart" "Completed Registration" etc...
Recording these standard events gives you access to specific bidding features on Facebook ads that you don't get without the events.
I have an app that has the React Native FBSDK
There are two methods for defining an event - one for purchases and one for everything else as seen here
There is zero documentation for standard events on react within the SDK on Github or on the event tracking docs on Facebook's developer platform.
Right now I'm trying to track the standard events by using their various names, as recorded across FB's documentation. I've tried the following:
AppEventsLogger.logEvent('FBSDKAppEventNameCompletedRegistration');
AppEventsLogger.logEvent('CompletedRegistration');
AppEventsLogger.logEvent('Completed Registration');
All of these just create custom events with those names, but aren't recognized as standard events.
Has anyone gotten standard events to work using the React Native wrapper for the FB SDK? If so how do you name the events to get FB to recognize them?
Update: As the comment below highlights, the more recent link is https://developers.facebook.com/docs/marketing-api/app-event-api/
It looks like you'll have to pass the strings that those standard events get evaluated to, i.e. instead of 'FBSDKAppEventNameCompletedRegistration', you'll have to use: 'fb_mobile_complete_registration'.
Here's the source:
Sorry if this is a bit late. Hope this helps.
I managed to find the actual event name by generating standard event code using tool on Facebook's documentation, run the code in AppDelegate.m, and get the exact key-values from Events Manager. With this roundabout way, I realized the actual name of Add to Cart event was fb_mobile_add_to_cart. From there I googled for the name and found the list documented in Marketing API (why not App Events?).
I don't know if it is the right place, but you can refer to https://developers.facebook.com/docs/marketing-api/app-event-api/ for actual standard event names and parameter names. At least it worked in my case. Here's my Add to Cart event code:
function logAddToCart(totalPrice, contentType, contentId, currency) {
const params = {
'fb_content_type': contentType,
'fb_content_id': contentId,
'fb_currency': currency
};
AppEventsLogger.logEvent('fb_mobile_add_to_cart', totalPrice, params);
}
I made a simple package with all events. Just import like
import FBEvents from "react-native-fbsdk-events";
// ...
AppEventsLogger(FBEvents.COMPLETE_REGISTRATITON, params);

Real time model events in Sails.js 0.10-rc5

I've been playing around with building some realtime functionality using Sails.js version 0.10-rc5 (currently the #beta release).
To accomplish anything, i've been following the sweet SailsCast tutorial on this subject (sailsCast link)
It talks about subscribing to a model via a 'subscribe' action within the model's controller. Then listening to it at the client side, waiting for the server to emit messages. Quite straightforward, although I do not seem to receive any messages.
I'm trying to do this to get real-time updates on anything that changes in my User models, or if new ones get created.. So I can display login status etc. in real time. Pretty much exactly the stuff that's explained in the sailsCast.
In my terminal i'll get two things worth noticing, of which the first is the following:
debug: Deprecated: `Model.subscribe(socket, null, ...)`
debug: See http://links.sailsjs.org/docs/config/pubsub
debug: (⌘ + double-click to open link from terminal)
debug: Please use instance rooms instead (or raw sails.sockets.*() methods.)
It seems like the 'subscribe' method has been deprecated. Could anybody tell me if that's correct, and tell me how to fix this? I've been checking out the reference to the documentation in the debug message, although it just points me to the global documentation page. I've been searching for an answer elsewhere, but haven't found anything useful.
The second message I'm getting is:
warn: You are trying to render a view (_session/new), but Sails doesn't support rendering views over Socket.io... yet!
You might consider serving your HTML view normally, then fetching data with sockets in your client-side JavaScript.
If you didn't intend to serve a view here, you might look into content-negotiation
to handle AJAX/socket requests explictly, instead of `res.redirect()`/`res.view()`.
Now, i'm quite sure this is because I have an 'isAuthenticated' policy added to all of my controllers and actions. When a user is not authenticated, it'll redirect to a session/new page. Somebody must log in to be able to use the application. When I remove the 'isAuthenticated' policy from the 'subscribed' action, the warnings disappear. Although that means anyone will get updates via sockets (when I get it to work), even when they're logged out. - I don't really feel like people just sitting at the login screen, fishing out the real time messages which are intended only for users who are logged in.
Can anyone help me getting the real time updates to work? I'd really appreciate!
As far as the socket messages not being received, the issue is that you're following a tutorial for v0.9.x, but you're using a beta version of Sails in which PubSub has gone through some changes. That's covered in this answer about the "create" events not being received.
Your second issue isn't about sockets at all; you'll just need to reconsider your architecture a bit. If you want to to use socket requests to sign users in, then you'll have to be more careful about redirecting them because, as the message states, you can't render a view over a socket. Technically you could send a bunch of HTML back to the client over a socket, and replace your current page with it, but that's not very good practice. What you can do instead is, in your isAuthenticated policy, check whether the request is happening via sockets (using req.isSocket) and if so, send back a message that the front end can interpret to mean, "you should redirect to the login page now". Something like:
module.exports = function (req, res, next) {
if ([your auth logic here]) {
return next();
}
else {
if (req.isSocket) {
return res.json({status: 403, redirectTo: "/session/new"});
} else {
return res.redirect("/session/new");
}
}
}