I have front-end GA4 implementation and want to send transactions data (and some custom events) from the server via MP. With recomendations of Google to
include session_id as a param, so that measurement protocol events
appear in session-based reporting
is it better to get session_id from gtag.js or generate random session_id?
I think I found the solution here https://www.optimizesmart.com/what-is-measurement-protocol-in-google-analytics-4-ga4/#11-10-session-id-
There 2 params in the request to GA:
"cid" - it's "GA client_id"
"sid" - this is session_id and you need to save it in your DB near "cid" param and then send it using measurement protocol along with client_id
According to Measurement Protocol (Google Analytics 4)/Sending events using random value for 'session_id' parameter will start new session.
According to Measurement Protocol (Google Analytics 4)/Changelog 'session_id' is required to get server-side events in session-based reports.
Solution:
'Session Id' is stored in cookies and seems it's a timestamp of session start date. To get 'Session Id' at server side using PHP:
/**
* Gets GA Session Id (GA4 only) from cookies.
*
* #var string $measurement_id
* GA4 Measurement Id (Property Id). E.g., 'G-1YS1VWHG3V'.
*
* #return int
* Returns GA4 Session Id or NULL if cookie wasn't found.
*/
function _get_browser_session_id($measurement_id) {
// Cookie name example: '_ga_1YS1VWHG3V'.
$cookie_name = '_ga_' . str_replace('G-', '', $measurement_id);
if (isset($_COOKIE[$cookie_name])) {
// Cookie value example: 'GS1.1.1659710029.4.1.1659710504.0'.
// Session Id: ^^^^^^^^^^.
$parts = explode('.', $_COOKIE[$cookie_name]);
return $parts[2];
}
}
Related
I have list of channel id of particular group, I want the group Id and name from channel Id.
Is there any such api in Microsoft graph api?
This is not possible with the Graph API. This has been confirmed by Microsoft.
However, when you are working with a channel object and have its id, you usually also have an id of the team it belongs to - for example in the bot framework, it's part of the activity's channelData.
Be prepared not to always have this information, since not all channels of conversations might be Teams channels! But let's assume you're working with Teams channels exclusively.
The id of the team is also the id of its implicitly-generated General channel. You can distinguish that one by the id format 19:…#thread.tacv2 - a normal channel has a hex string whereas the team itself has a longer base62 string and includes a -. Without this id, you're basically lost.
Unfortunately, this team id is still mostly useless. It is not the UUID that you use in the Graph API for the Team resources (at /teams/{team-id}), Channel resources (at /teams/{team-id}/channels/{channel-id}) and Group resources ("Every team is associated with a Microsoft 365 group. The group has the same ID as the team - for example, /groups/{id}/team is the same as /teams/{id}").
Rather, it is the value of the internalId property of the team. It is also the main part of its webUrl. So how to get the groupId/teamId UUID of the team from its internalId string?
The best you can do with the Graph API is to get a list of all teams (either via /groups or via /teams, or at least the teams that you are part of or are otherwise associated with), and then for each team fetch the whole object by id and compare its internalId with the channel id / internal team id that you are looking for.
Unfortunately, /teams?$filter=internalId eq '19%3A…%40thread.tacv2' only gives the response Filter on property 'internalId' is not supported. :-/
However, looking outside of the Graph API, there is the Bot Framework REST API (part of Azure Bot Services), which does provide an undocumented endpoint. I discovered it via this StackOverflow answer, which shows that the Bot Framework SDK for .NET does have a method to fetch this information: FetchTeamDetailsWithHttpMessagesAsync. It takes an internal teamId (which is not distinguished in the documentation) and returns a TeamDetails object which contains an AadGroupId property: "Azure Active Directory (AAD) Group Id for the team." That's the one we want!
And since the code is open-sourced on Github, we can find its implementation:
// Construct URL
var baseUrl = Client.BaseUri.AbsoluteUri;
var url = new System.Uri(new System.Uri(baseUrl + (baseUrl.EndsWith("/", System.StringComparison.InvariantCulture) ? string.Empty : "/")), "v3/teams/{teamId}").ToString();
url = url.Replace("{teamId}", System.Uri.EscapeDataString(teamId));
This works similar in JavaScript/TypeScript, except the SDK doesn't expose the method itself. Turns out I need to look better, it's available as TeamsInfo.getTeamDetails (working from the current TurnContext) or new Teams(client).fetchTeamDetails. Looking at its implementation, it uses
const fetchTeamDetailsOperationSpec: msRest.OperationSpec = {
httpMethod: 'GET',
path: 'v3/teams/{teamId}',
…
};
I'll leave my custom implementation up for posterity still, it has slightly more accurate types:
const SERVICE_URL = 'https://smba.trafficmanager.net/…/';
async function fetchTeamDetails(teamInternalId: string): Promise<TeamDetails> {
const adapter = new BotFrameworkAdapter({
…
});
const client = adapter.createConnectorClient(SERVICE_URL);
const response = await client.sendRequest({
method: 'GET',
url: `${SERVICE_URL}/v3/teams/${encodeURIComponent(teamInternalId)}`,
});
return response.parsedBody as TeamDetails;
}
/** Details related to a team. Modelled after https://learn.microsoft.com/en-us/dotnet/api/microsoft.bot.schema.teams.teamdetails (which is lacking `tenantId` though) */
interface TeamDetails {
/** Unique identifier representing a team. */
id: string;
/** Tenant Id for the team. */
tenantId: string; // UUID
/** Azure Active Directory (AAD) Group Id for the team. */
aadGroupId: string; // UUID
/** type of the team */
type: 'standard' | 'sharedChannel' | 'privateChannel';
/** Name of team. */
name: string;
/** Number of channels in the team. */
channelCount: number;
/** Number of members in the team. */
memberCount: number;
}
Reverse is possible.
If you have Group/team id, can get channels. But no API to get Group id based on Channel id.
Is there a way to get "User Google Id" from the session in App Maker. In the documentation its only mentioned how to retrieve the email of the logged in user Session.getActiveUser().getEmail() but no where it says how to get the id. I need this because the user email might sometimes changes. So I need the user id to keep track of users and related permission tasks. Or is there something I'm missing out here in how this should be implemented.
Yet an easier way to find Google Id simply using the Directory model. Although its mentioned in documentation that there is a way to get current signed in user id ( which is Google Id), its not clearly stated how - maybe documentation could be improved here. Another problem is that in many occasions the email of current active user is referred to as the id for example in deprecated method Session.getActiveUser().getUserLoginId(). Anyways this is a proper way to get the id.
var query = app.models.Directory.newQuery();
query.filters.PrimaryEmail._equals = Session.getActiveUser().getEmail();
var result = query.run();
var GoogleId = result[0]._key;
So with this GoogleId you can safely relate different models with each other and not worry that database integrity might break if an already referenced user email is changed.
Relating the different models could be done simply by creating a model that acts as a wrapper model around the Directory model and storing GoogleId in it. Then linking that model to other models where you want to track user related data because unfortunately we can not directly link The Directory Model to other models.
A team member has figured it out. This should be done using Apps Script - which works within App Maker environment using server side script.
var GoogleUser = (function (){
/**
*
* #param {string} email
*/
function getUserObjByEmail(email){
// Same as using AdminDirectory class.
var apiUrl = "https://www.googleapis.com/admin/directory/v1/users/"+email+"?fields=id";
var token = ScriptApp.getOAuthToken();
var header = {"Authorization":"Bearer " + token};
var options = {
"method": "GET",
"headers": header
};
var response = JSON.parse(UrlFetchApp.fetch(apiUrl, options));
return response;
}
/**
*
* #param {string} email - User email.
*/
function getIdByEmail(email){
return getUserObjByEmail(email)['id'];
}
var publicApi = {
getIdByEmail: getIdByEmail
};
return publicApi;
})();
Note that using var apiUrl = "https://www.googleapis.com/admin/directory/v1/users/"+email+"?fields=id"; is not going to be asynchronously called because its already happening in the server.
Is this a dup of this question?
I think this will solve your problem, even though it's a bit of a hack.
Google Analytics is correctly reporting exceptions thrown by my Android app. And I can use Scheduled Emails to send this report to me. However, receiving a daily email when there isn't anything to report (i.e., the report tells me that zero exceptions occurred) is tedious. Thus, I'd like to receive emails only when there is something to report (i.e., the report tells me that one or more exceptions occurred). It seems that Custom Alerts can be used for this purpose. However, Custom Alerts do not appear to be compatible with Exceptions. This leads me to my question.
Can Custom Alerts be configured to provide email notification on exceptions?
Or, more generally,
Can Google Analytics be configured to provide email notification on exceptions?
Also, does this work for crashes too?
UPDATE (22 Nov 2015, 1 Dec 2015)
(Partial) answer. I provide an answer that enables a server (not Google Analytics) to be configured to provide email notification on exceptions, which is probably a sufficient solution for many.
(Almost an) answer. jakub-kriz has provided a detailed answer, but it does not work as-is. Building upon the answer, I was able to configure Google Analytics to email when no exceptions occur. This is the exact opposite of what is required. Unfortunately, I have been unable to get emails when one or more exceptions occur.
Alternate direction. jakub-kriz has proposed an alternative solution, whereby normal events are used, rather than exception events. I haven't tried this direction.
A complete solution has not yet been proposed.
It is possible, but not in a direct way, you have to hookup you analytics quite dirty.
1) Configuration in Analytics Admin
Create two filters in Admin -> View -> Filters -> Custom -> Advanced
Create filter that listens on hitType exception and set Event Category - Exception
Create filter that replicates Exception description into Event Action
2) Create custom Goal
Create two filters in Admin -> View -> Goals -> Custom -> Event
Event Category equals Exception
3) Create Custom Alert
Custom alert by Goal containg exception
Do not forget your email
Try this and let me know!
To get report on Mail Id there is no way to send directly from google analytics. We can send this error report handling it and send it to programmatically to mail id from our app.
A server (not Google Analytics) can be configured to provide email notification on exceptions, which is probably a sufficient solution for many.
First, you need a service account, which can be created https://console.developers.google.com/project/_/apiui/credential. You'll create a key file (MyAnalytics.p12).
Secondly, we configure our analytics client (MyAnalytics.php):
<?php
//You'll need to install google-api-php-client
//(https://github.com/google/google-api-php-client)
require_once 'Google/autoload.php';
class MyAnalytics
{
//When logged into Google Analytics you'll have a URL that looks
//something like https://www.google.com/analytics/web/?authuser=0#home/a00w11p22/
//Your profile id is everything after the p
const PROFILE_ID = '22';
//This is the service account email that you constructed in step 1
const SERVICE_ACCOUNT_EMAIL = 'blah#developer.gserviceaccount.com';
//This is the file that you constructed in step 1.
const KEY_FILE_LOCATION = 'MyAnalytics.p12';
private $client;
private $analytics;
private $cred;
public function __construct() {
$this->client = new Google_Client();
$this->analytics = new Google_Service_Analytics($this->client);
$key = file_get_contents(self::KEY_FILE_LOCATION);
$this->cred = new Google_Auth_AssertionCredentials(
self::SERVICE_ACCOUNT_EMAIL,
array(Google_Service_Analytics::ANALYTICS_READONLY),
$key
);
}
public function getAnalytics() {
$this->client->setAssertionCredentials($this->cred);
if($this->client->getAuth()->isAccessTokenExpired()) {
$this->client->getAuth()->refreshTokenWithAssertion($this->cred);
}
return $this->analytics;
}
}
?>
Thirdly, we query and report on exceptions (exceptions.php):
<?php
require_once 'MyAnalytics.php';
$myAnalytics = new MyAnalytics();
$analytics = $myAnalytics->getAnalytics();
$results = $analytics->data_ga->get(
'ga:' . MyAnalytics::PROFILE_ID,
'yesterday',
'today',
'ga:exceptions'
);
$a = $results->getTotalsForAllResults();
$count = $a['ga:exceptions'];
echo $count;
if (is_numeric($count) && $count > 0) {
//handle the exception, e.g., send an email
//(cf. https://stackoverflow.com/a/5335311/3664487)
}
?>
Fourth, configure cron to run exceptions.php (cf. https://stackoverflow.com/a/22358929/3664487).
I need to keep the new member's origin. I use utm_source for every external source. How can I keep that record from the utm_source inside link when a user from a source e.g. utm_source=facebook, come to my site and sign up? I need to see the source for each members in my database.
Google Analytics stores visitor referral information in a cookie called __utmz. After this cookie is set, its contents will be sent with every subsequent request to your domain from that user. So, when a user signs up, you can grab the contents of this cookie and save it to your database. Below are a few links that should help get you started.
Catching UTM Params in Rails
http://blog.rjmetrics.com/2012/09/06/how-to-save-google-analytics-referrer-data-to-database/
It's not working anymore. I save utm into cookies via js and then save it into DB.
Here is a js script:
// Save UTM into cookies
var url = new URL(window.location.href);
var utm_date = new Date(new Date().getTime() + 365 * 24 * 60 * 60 * 1000);
var utm_source = url.searchParams.get("utm_source");
if (utm_source) {
document.cookie = "utm_source="+utm_source+"; expires=" + utm_date.toUTCString();
}
var utm_medium = url.searchParams.get("utm_medium");
if (utm_medium) {
document.cookie = "utm_medium="+utm_medium+"; expires=" + utm_date.toUTCString();
}
var utm_campaign = url.searchParams.get("utm_campaign");
if (utm_campaign) {
document.cookie = "utm_campaign="+utm_campaign+"; expires=" + utm_date.toUTCString();
}
Meteor has a loginWithToken method, and there are resume tokens in the user object. So one can login using one of these tokens with loginWithToken. That works.
Is there a way to generate new login tokens, or should I just use the resume tokens to create a quick login link?
As Johnny said, you can use the Accounts._generateStampedLoginToken() function, which is actually nothing special, just the following function:
_generateStampedLoginToken = function () {
return {
token: Random.secret(),
when: new Date
};
}
anyway, to use it, here is an example:
// Server //
// Creates a stamped login token
var stampedLoginToken = Accounts._generateStampedLoginToken();
/**
* Hashes the stamped login token and inserts the stamped login token
* to the user with the id specified, adds it to the field
* services.resume.loginTokens.$.hashedToken.
* (you can use Accounts._hashLoginToken(stampedLoginToken.token)
* to get the same token that gets inserted)
*/
Accounts._insertLoginToken(user._id, stampedLoginToken);
// Client //
// Login with the stamped loginToken's token
Meteor.loginWithToken(stampedLoginToken.token);
Yes, you can generate new tokens by calling Accounts._generateStampedLoginToken(). You can call it from within a login handler.
https://github.com/meteor/meteor/blob/master/packages/accounts-base/accounts_server.js#L114
it's 2015 - use one of these packages:
poetic:accounts-passwordless
acemtp:accounts-passwordless
http://fastosphere.meteor.com/?q=passwordless