How to configure gatsby-plugin-google-analytics with cookies consent? - google-analytics

I have developed a website using gatsby and I am using google analytics plugin via gatsby-plugin-google-analytics, now to be nice with the users, I would like to add a cookie consent where the user will be two options whether to accept or decline cookies usages. If the user declines then I would like to stop google analytics to track the user activity. I dug into their documentation but unable to find the option to achieve this, is there any way around to achieve this.
{
resolve: `gatsby-plugin-google-analytics`,
options: {
trackingId: siteConfig.googleAnalyticsId,
// Defines where to place the tracking script - `true` in the head and `false` in the body
head: false,
},
},
For the movement my gatsby-config.js looks like this. how one can achieve this.
Thanks you in advance.

The plugin merely loads the library and instruments page tracking calls in a Gatsby-compatible way for you. All of the other Google Analytics calls, including disabling measurement for a user works the same as normal.
It's up to you to:
Build and show a cookie notice with an opt-out
Remember when a user has opted out
Communicate this on each page-load for the user (before any ga() calls are made) by setting window['ga-disable-UA-XXXXX-Y'] = true
You should be able to do this in a function exported as onClientEntry from gatsby-browser.js. For example:
export const onClientEntry = () => {
if (userHasOptedOutOfThirdPartyTracking()) {
window[`ga-disable-${process.env.GATSBY_GOOGLE_ANALYTICS_ID`] = true
}
}

For the Gatsby website, you could use a combination of gatsby-plugin-gdpr-cookies for analytics cookies management in your gatsby-config.js and react-cookie-consent to display the cookie banner.
# using npm
npm install --save gatsby-plugin-gdpr-cookies react-cookie-consent
# using yarn
yarn add gatsby-plugin-gdpr-cookies react-cookie-consent
You can find a more detailed tutorial here.

Related

Firebase 3rd-party AuthProvider (Google/Facebook/etc) login with chrome extension manifest v3

Manifest version 3 for Chrome extensions have been killing me lately. Been able to navigate around it so far, but this one has really stumped me. I'm trying to use Firebase authentication for a Chrome extension, specifically with 3rd party auth providers such as Google and Facebook. I've setup the Firebase configuration for Login with Google and created a login section in the options page of the Chrome extension and setup the Firebase SDK.
Now, there are two login options when using an auth provider, signInWithRedirect and signInWithPopup. I've tried both of these and both have failed for different reasons. signInWithRedirect seems like a complete dead end as it redirects to the auth provider, and when it attempts to redirect back to the chrome-extension://.../options.html page, it just redirects to "about:blank#blocked" instead.
When attempting to use signInWithPopup, I instead get
Refused to load the script 'https://apis.google.com/js/api.js?onload=__iframefcb776751' because it violates the following Content Security Policy directive: "script-src 'self'". Note that 'script-src-elem' was not explicitly set, so 'script-src' is used as a fallback.
In v2, you could simply add https://apis.google.com to the content_security_policy in the manifest. But in v3, the docs say
"In addition, MV3 disallows certain CSP modifications for extension_pages that were permitted in MV2. The script-src, object-src, and worker-src directives may only have the following values:"
self
none
Any localhost source, (http://localhost, http://127.0.0.1, or any port on those domains)
So is there seriously no way for a Google Chrome extension to authenticate with a Google auth provider through Google's Firebase? The only workaround I can think of is to create some hosted site that does the authentication, have the Chrome extension inject a content script, and have the hosted site pass the auth details back to the Chrome extension through an event or something. Seems like a huge hack though and possibly subject to security flaws. Anyone else have ideas??
Although it was mentioned in the comments that this works with the Google auth provider using chrome.identity sadly there was no code example so I had to figure out myself how to do it.
Here is how I did it following this tutorial:
(It also mentions a solution for non-Google auth providers that I didn't try)
Identity Permission
First you need permission to use the chrome identity API. You get it by adding this to your manifest.json:
{
...
"permissions": [
"identity"
],
...
}
Consistent Application ID
You need your application ID consistent during development to use the OAuth process. To accomplish that, you need to copy the key in an installed version of your manifest.json.
To get a suitable key value, first install your extension from a .crx file (you may need to upload your extension or package it manually). Then, in your user data directory (on macOS it is ~/Library/Application\ Support/Google/Chrome), look in the file Default/Extensions/EXTENSION_ID/EXTENSION_VERSION/manifest.json. You will see the key value filled in there.
{
...
"key": "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAgFbIrnF3oWbqomZh8CHzkTE9MxD/4tVmCTJ3JYSzYhtVnX7tVAbXZRRPuYLavIFaS15tojlRNRhfOdvyTXew+RaSJjOIzdo30byBU3C4mJAtRtSjb+U9fAsJxStVpXvdQrYNNFCCx/85T6oJX3qDsYexFCs/9doGqzhCc5RvN+W4jbQlfz7n+TiT8TtPBKrQWGLYjbEdNpPnvnorJBMys/yob82cglpqbWI36sTSGwQxjgQbp3b4mnQ2R0gzOcY41cMOw8JqSl6aXdYfHBTLxCy+gz9RCQYNUhDewxE1DeoEgAh21956oKJ8Sn7FacyMyNcnWvNhlMzPtr/0RUK7nQIDAQAB",
...
}
Copy this line to your source manifest.json.
Register your Extension with Google Cloud APIs
You need to register your app in the Google APIs Console to get the client ID:
Search for the API you what to use and make sure it is activated in your project. In my case Cloud Firestore API.
Go to the API Access navigation menu item and click on the Create an OAuth 2.0 client ID... blue button.
Select Chrome Application and enter your application ID (same ID displayed in the extensions management page).
Put this client ID in your manifest.json. You only need the userinfo.email scope.
{
...
"oauth2": {
"client_id": "171239695530-3mbapmkhai2m0qjb2jgjp097c7jmmhc3.apps.googleusercontent.com",
"scopes": [
"https://www.googleapis.com/auth/userinfo.email"
]
}
...
}
Get and Use the Google Auth Token
chrome.identity.getAuthToken({ 'interactive': true }, function(token) {
// console.log("token: " + token);
let credential = firebase.auth.GoogleAuthProvider.credential(null, token);
firebase.auth().signInWithCredential(credential)
.then((result) => {
// console.log("Login successful!");
DoWhatYouWantWithTheUserObject(result.user);
})
.catch((error) => {
console.error(error);
});
});
Have fun with your Firebase Service...

eHow to transition away from inline editor on actions on google

In a previous Stack Overflow question, I shied away from using an external webhook on Actions on Google
so I needed to go back to the inline editor. I got that worked out, but now I'm feeling brave again.
I've outgrown the inline editor and want the ability to develop my code on my laptop, testing it in Firebase, and publishing to a site for my webhook, presumably where the inline code editor publishes to. In fact, I have already written the require functions and deployed them from Firebase. So the full functionality is ready to go, I just need to hook it up properly to Actions on Google.
What I have now in Actions on Google, inline editor, is more of a stub. I want to merge that stub into my more fullblown logic that I have in Firebase. Here is what is in the inline editor:
const { conversation } = require('#assistant/conversation');
const functions = require('firebase-functions');
const app = conversation();
app.handle('intent_a_handler', conv => {
// Implement your code here
conv.add("Here I am in intent A");
});
app.handle('intent_b_handler', conv => {
// Implement your code here
conv.add("Here I am in intent B");
});
exports.ActionsOnGoogleFulfillment = functions.https.onRequest(app);
When I search on the Internet, I see discussion from the point of view of Dialogflow, but like I say, I'm in "Actions on Google". I want to transition away from the inline editor, taking what I already have, as a basis.Can someone explain how I set that up? I'm happy to do this within the context of the Google ecosystem.
To test your own webhook locally on your own system I would recommend incorporating a web app framework such as express. With express you can host code on your local machine and make it respond to request from Actions on Google. In your case you would replace this will all the code related to the Firebase functions package. Here is an example of what a simple webhook for Actions on Google looks like:
const express = require('express');
const bodyParser = require('body-parser')
const { conversation } = require('#assistant/conversation');
const exprs = express();
exprs.use(bodyParser.json()) // allows Express to work with JSON requests
const app = conversation();
app.handle('example intent', () => {
// Do something
})
// More app.handle() setups
exprs.post('/', app);
exprs.listen(3000);
With this setup you should be able to run your own application locally. The only thing you need to do is install the required dependencies and add your own intent handlers for your action. At this point you have a webhook running on your own machine, but that isn't enough to use it as a webhook in Actions on Google because it runs locally and isn't publicly available via the internet.
For this reason we will be using a tool called ngrok. With ngrok you can create a public https address that runs all messages to your local machine. This way you can use ngrok address as your webhook URL. Now you can just make as many code changes as you want and Actions on Google will automatically use the latest changes when you develop. No need to upload and wait for Firebase to do this.
Just to be clear: Ngrok should only be used for development. When you are done with developing your action you should upload all your code to a cloud service or host it on your own server if you have any. A (free plan) ngrok URL usually expires every 6 hours. So its not a suitable solution for anything other than development.

meteor-shopify authenticator getPermanentAccessToken with code

I'm using the froatsnook:shopify atmosphere package to create an embedded public app on Shopify. I currently have a couple issues:
1) Getting the access token from the "code" query parameter after a user authenticates. As it mentions in the docs here, I'm supposed to use authenticator.getPermanentAccessToken(code) but what I don't understand is how to get call authenticator if the "code" parameter appears on the callback route (at that point, the authenticator I instantiated on the client pre-auth route is out of scope).
2) The "oAuth" function callback is never called for some reason, even when assigning it to Shopify.onAuth on the server.
3) The difference between post_auth_uri and redirect_uri ?
// I call this during 'onBeforeAction' for iron-router
function beforeAuth (query) {
// is this necessary..?
console.assert(Meteor.isClient);
// get shop name like 'myshop' from 'myshop.shopify.com';
const shop = query.shop.substring(0, query.shop.indexOf('.'));
// use api_key stored in settings
var api_key = Meteor.settings.public.shopify.api_key;
// Prepare to authenticate
var authenticator = new Shopify.PublicAppOAuthAuthenticator({
shop: shop,
api_key: api_key,
keyset: 'default',
embedded_app_sdk: true,
redirect_uri: 'https://45a04f23.ngrok.com/testContent',
//post_auth_uri: ???
// This is doesn't seem to be getting
// called after clicking through the OAuth dialog
onAuth: function(access_token) {
ShopifyCredentials.insert({
shop: shop,
api_key: api_key,
access_token: access_token
});
}
});
// Should i use something different with iron-router?
location.href = authenticator.auth_uri;
// how do i get code in this scope???
// authenticator.getPermanentAccessToken(code);
}
There are a few issues with the way you are trying to set up the authenticator, although it's not really your fault because the way Scenario 3 works in the docs is not an 'out of the box' solution and requires a bunch of custom code, including your own handler (I can provide a gist if you REALLY want to build your own handler, but I suggest using the new server-side onAuth callback instead)
1. Specifying a redirect_uri overrides the package's default redirect_uri handler which is Meteor.absoluteUrl("/__shopify-auth").
So instead, completely remove redirect_uri and put your testContent url in post_auth_uri instead.
2. ShopifyCredentials does not exist in this package. If you want to use it that way, make sure you actually have defined a collection called 'ShopifyCredentials' and insert the record from the server, not the client. Note that you will still need to add a keyset on the server for the API methods to work. If you are using user accounts and would like to permanently store credentials, I suggest saving the credentials to the database and adding the keyset via a server-side onAuth callback.
3. authenticator.getPermanentAccessToken(code) isn't useful unless you are using your own handler. Instead, you can just get access_token from the onAuth callback.
Also keep in mind that if you ever need to reauthenticate from inside the embedded app, you need to use window.top.location.href to break out of the iframe.
If you want a complete, working boilerplate example with user accounts see my gist here:
Authentication with Accounts and Persistent Keysets
If you aren't using accounts, you can use this gist instead, but please note that you really need to come up with some way to check that the current client has permission to request the keyset for a given shop before going to production:
Authentication with Persistent Keysets

Accessing YouTube API in Meteor project for logged in user

I'm working on a new Meteor project which involves users logging into the site using their Google accounts through OAuth (I'm using the Meteor accounts-google package for this) and when signing in I need them to be able to see some data from the YouTube Analytics API for their YouTube channel. As of now the data I am trying to get is their total daily views, which I then hope to display on a chart for a specified time period.
I have added the following scopes to my accounts-google login system:
Meteor.loginWithGoogle({
requestPermissions: ['https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile', 'https://www.googleapis.com/auth/yt-analytics.readonly', 'https://www.googleapis.com/auth/youtube.readonly'],
requestOfflineToken: true,
forceApprovalPrompt: true,
loginStyle: "popup"
});
This all seems to be working very well, once a user signs into the site and grants the site access to these I can then see the necessary info in my MongoDB database. Under user.services.google I can now see it has accessToken, idToken, expiresAt, refreshToken, etc.
I've also decided to use the google api nodejs client by implementing it through the meteorhacks:npm package for Meteor. I am using this to refresh tokens (as seen in this SO answer I found helpful).
Using the "Try It" API Explorer on the YouTube Analytics API Documentation page, I can get the type of data I'm looking for through this request:
GET https://www.googleapis.com/youtube/analytics/v1/reports?ids=channel%3D%3DMINE&start-date=2015-10-01&end-date=2015-10-31&metrics=views&dimensions=day&sort=-day&key={YOUR_API_KEY}
Now is where I've been completely stuck and really unsure of where to go from here. How can I implement this into my site? I've tried for quite some time now to make this work but everything I attempt isn't working, and there's no real direction. If anyone is willing to help out I'd greatly appreciate it. I'm fairly new to Meteor/JS/APIs so any information/examples is extremely appreciated, especially noob friendly stuff! ;)
One way to do it is to use a method and the http package: https://atmospherejs.com/meteor/http
Looking at the doc you provide, you may try something like this:
Define your method on the server side
// server-side
Meteor.methods({
getYoutubeReports: function(channelId, accessToken, params) {
params.ids = "channel=="+ channelId;
params.key = accessToken;
return HTTP.get("https://www.googleapis.com/youtube/analytics/v1/reports", {
params: params
});
}
});
You can then call it on the client side with the data you get from your the authentication (ie. CHANNEL_ID_OF_MY_USER & ACCESS_TOKEN_OF_MY_USER)
// client-side
var reports,
myParams = {
"start-date": "2015-10-01",
"end-date": "2015-10-31",
"metrics": "views",
"dimensions": "day",
"sort": "-day"
};
Meteor.call('getYoutubeReports', CHANNEL_ID_OF_MY_USER, ACCESS_TOKEN_OF_MY_USER, params, function(error, result) {
// store or do stuff with the result of the HTTP request here
console.log(result);
});
Feel free to custom myParams as your user need!
And if you want to some more tips about how to use HTTP request (really useful to call external API), The Meteor Chef wrote a really good article about it : https://themeteorchef.com/snippets/using-the-http-package/
I hope it helps!
I ended up using the percolate:google-api package to handle my API call.

Display 'Pure HTML Dashboards' or 'Custom Components' using Analytics Api

I need to display 'Pure HTML Dashboards' or 'Custom Components' as depicted in the following link https://ga-dev-tools.appspot.com/demos/embed-api/
I have google analytics account & it shows me the real time statistics perfectly for my website, but i need to display the same using the api as shown in the following link:
https://github.com/googleanalytics/embed-api-demos/blob/master/site/3-custom-components.html
I have replaced my client id in the following code:
gapi.analytics.auth.authorize({
container: 'auth',
clientid: '623325626209-j1jm9d78ge0v4uf8b9cor31qsirungrq.apps.googleusercontent.com',
});
I also updated the end date to current date as follows:
query: {
'metrics': 'ga:sessions',
'dimensions': 'ga:date',
'start-date': '30daysAgo',
'end-date': '2014-09-05'
},
So when i run the code it shows a button "Access Google Analytics", when i click on it i get the following error:
That’s an error.
Error: origin_mismatch
Application: Project Default Service Account
You can email the developer of this application at: fz1990#gmail.com
Request Details
=
scope=https://www.googleapis.com/auth/analytics.readonly https://www.googleapis.com/auth/userinfo.email
response_type=code token id_token gsession
redirect_uri=postmessage
cookie_policy=single_host_origin
proxy=oauth2relay591552393
state=524099008|0.3938720987
origin=http://localhost:27363
include_granted_scopes=true
client_id=656169223314-dbc8l4c7ro20hn8vcqqtd9rhd0e6arcb.apps.googleuserconte
Can somebody plss help me to fix this issue?
Thanx in advance
Origin mismatch is normally caused by the Javascript origins not being set correctly in the API project console. You need to make sure that the Javascript origins match the domain from which your requests are coming and to which you are returning the user after sign in.
In your case you are still using the client_id from the tutorial you need to create your own. More details can be found in the developer documentation for the embeded API in the "Create a client ID and client secret" section.
Basilcy you need to go to Google Developer console and register your application. The link above to the documentation will walk you though creating that. Hint: don't for get to add a product name and email address.
At this time the Real-time API is still in beta you will need to apply for access to it. Real time reporting api private beta fill out that form you wont hear anything from Google just wait 24 hours and give it a try it normally works by then.

Resources