I am trying to implement tracking acceptance on a Gatsby site using gatsby-plugin-google-gtag and a custom cookie prompt component.
Currnetly the tracking code is setup and working and the cookie prompt component is conditionally rendering depending if the user has previously made their choice regarding tracking. Where things are failing is trying to conditionally set anonymize_ip based on the users choice. I have tried to set true/false based on a ternary statement in gatsby-config.js, but this seems to error login issues in terminal relating to GraphQL (not linked).
anonymize_ip: document.cookie.match(/^(.*;)?\s*ga-disabled\s*=\s*[^;]+(.*)?$/) ? true : false, // If cookie exists, set value to true
Does anyone know the best way to achieve this?
Thanks
Cookie Prompt
import React from "react";
import { setCookie } from "../../assets/js/utils/cookies";
const CookiesPrompt = () => {
const gaOptout = () => {
setCookie('ga-disabled', true, 30);
}
const gaAccept = () => {
setCookie('ga-hide-prompt', true, 30);
}
return (
<div className="cookies-prompt">
<div className="cookies-prompt__wrap">
<div className="cookies-prompt__title">This website uses cookies</div>
<button onClick={() => gaOptout()} className="cookies-prompt__link button--non">I wish to opt-out</button>
</div>
<button onClick={() => gaAccept()} className="cookies-prompt__button button button--primary">Accept</button>
</div>
);
};
export default CookiesPrompt;
Gatsby-config.js
plugins: [
"gatsby-plugin-sass", "gatsby-plugin-react-helmet", "gatsby-transformer-json", "gatsby-plugin-image", "gatsby-plugin-sharp", "gatsby-transformer-sharp",
{
resolve: `gatsby-plugin-google-gtag`,
options: {
// You can add multiple tracking ids and a pageview event will be fired for all of them.
trackingIds: [
'G-xxxxxxx', // Google Analytics / GA
],
// This object gets passed directly to the gtag config command
// This config will be shared across all trackingIds
gtagConfig: {
// optimize_id: 'OPT_CONTAINER_ID',
anonymize_ip: document.cookie.match(/^(.*;)?\s*ga-disabled\s*=\s*[^;]+(.*)?$/) ? true : false, // If cookie exists, set value to true
cookie_expires: 0,
},
// This object is used for configuration specific to this plugin
pluginConfig: {
// Puts tracking script in the head instead of the body
head: false,
// Setting this parameter is also optional
respectDNT: true,
// Avoids sending pageview hits from custom paths
exclude: ['/preview/**', '/do-not-track/me/too/'],
},
},
},
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'data', // Identifier. Will then be queried as `dataJson`
path: './src/assets/data', // Source folder containing the JSON files
},
},
{
resolve: 'gatsby-source-filesystem',
options: {
name: 'projectImages', // Identifier. Will then be queried as `projectImagesJson' ?
path: './public/static/projects', // Source folder containing the JSON files
},
},
]
gatsby-config.js configurations are set on build-time, not on runtime, so there's no way that you can listen document in that environment/file on-demand.
However, you can use the anonymize IP based on user choice (onClick) by triggering the gaOptout() function:
<div onClick={gaOptout}>Deactivate Google Tracking</a>
Where gaOptout:
function gaOptout() {
;(document.cookie =
disableStr + "=true; expires=Thu, 31 Dec 2099 23:59:59 UTC;path=/"),
(window[disableStr] = !0)
}
var gaProperty = "UA-XXXXXXXX-X",
disableStr = "ga-disable-" + gaProperty
document.cookie.indexOf(disableStr + "=true") > -1 && (window[disableStr] = !0)
Related
Here's my component:
{
path:"aaaa",
component: aaaa,
data: {
message: "this is aaaa"
},
resolve: {
setDraftResolver: SetDraftResolver, // I want this to run as normal
draft: GetDraftResolver, // I want this to operate as if runGuardsAndResolvers: "always",
},
// runGuardsAndResolvers: "always",
}
I have multiple resolvers in one component and I want only the GetDraftResolver to run every time. The others I want to run as they are currently.
Is this something that's possible to do in Angular?
I have an application where I try to put the language management but I face a difficulty.
I'm on the latest version of #nuxtjs/i18n. When I change language, my URl changes, my labels change, everything is fine. When I refresh my page, however, the system reverts to the old language.
Here is my conf:
[
'#nuxtjs/i18n',
{
locales,
defaultLocale,
lazy: true,
langDir: 'locales/',
vueI18n: {
fallbackLocale: defaultLocale,
},
},
],
['~/.build/merge-and-compare-locales.js', { defaultLocale }],
export const locales = [
{
code: 'en',
file: 'en.json',
},
{
code: 'fr',
file: 'fr.json',
},
]
export const defaultLocale = 'fr'
What more do I need to do to make it keep the language before refresh?
I specify that I use this method to change the language:
changeLocale(code: string) {
this.$i18n.setLocale(code)
},
Locally it works fine. On the other hand on any other environment it does not work, the refresh makes return to the default language
i have same problem and it's come from ssr...
inside your store/index you should have a nsi (nuxt server init) function
something like this.
/** initial the store when user fetch the web app */
async nuxtServerInit(ssrContext: Context) {
if (this.$i18n.locale==='ar') {
ssrContext.redirect("/ar");
}
else if (this.$i18n.locale === 'fa')
{
ssrContext.redirect('/')
}
}
I have a Vue project, but there is a issue to me,
In my router.js:
{
path: '/home/aftersale_physicalserver_workpanel/:use_flag/:areapartition_homeshowtext',
meta: { keepAlive: true },
icon: 'compose',
name: 'aftersale_physicalserver_workpanel',
title: 'work panel',
component: resolve => {
require(['./views/main_home/home/components/general_admin_staff_panel/physicalserver/physicalserver_workpanel.vue'], resolve);
}
},
there is the code:
...
<template>
<lml-page
ref="lml_page_ref"
v-if=" origin_data && origin_data.count"
:data_count="origin_data.count"
:current.sync="cur_page"
#change_page_for_parent="server_change_page">
</lml-page>
</template>
...
<script>
export default {
props: {
...
cur_page: 1,
},
</script>
you see the cur_page is the page number. I want the URL append the page number.
because when I enter a detail page, when I go back, there will go to page 1 by default.
My purpose
my purpose is let the list_page remember some params. such as the upper page_number, and some search params. but in Vue I don't know how.
When I from a searched params page enter a detail page, when I go back:
<span class="go-left" #click="$router.go(-1)">
<Icon type="chevron-left"></Icon>
<span>Go back</span>
</span>
there will get a list_page without the searched data.
You would need to use either local storage or a central state, what I use is vuex like this:
onPageChange: function (pageNo) {
this.$store.dispatch(this.$mts.some.SOMETHING, pageNo);
},
Then you can call your store wherever you need and get the page number.
Look for the vuex docs on how to setup state management.
Like this:
this.page = this.$store.getters.some.page
Im quite new to the vue reactive data workflow, and I'm attempting to make a image uploader, and its mainly working. Im trying to remove all true primary values from the images in the array, before updating a specific one. But I need to make a check on the "primary" values in the image array so i can make the conditional change.
I have left the image creation function at the bottom so you can see how this is made. the parent component gets all the data from server via ajax if being used to edit images this is the _images prop.
For some reason when i reference the array as images[key].primary, I get a different value than if I output the whole array in the console. Any ideas whats happening here?
Goal
Currently on the child component im clicking a make primary button and emitting the update to this component. Then in the update Method attempting to check if request is a new primary image request and make primary false on all other images. Then setting the requested image as primary. So a primary on toggle so there is only ever one primary image.
currently Im testing two images, in turn setting each one as primary true, and watching the other automatically turn false, but by the third click they are both true and nothing happens. Any ideas whats happening here?
Parent Component (v-image-upload):
export default {
components: {
'v-image': image
},
props: ['_errors', '_images', '_isMultiple'],
data() {
return {
images: _.cloneDeep(this._images),
}
},
methods: {
updateImage(request) {
//ISSUE: current images = true,true | images = false,true
console.log('current images', this.images[0].primary, this.images[1].primary, );
console.log('images', this.images);
if (request.form.primary && !this.images[request.key].primary) {
//reset all primary images
$.each(this.images, (index, value) => {
let image = value;
image.primary = false;
this.$set(this.images, index, image);
}
//update images with new image
this.$set(this.images, request.key, request.form);
},
onFileChange(e) {
let files = e.target.files || e.dataTransfer.files;
if (files.length) {
$.each(files, (index, file) => {
this.createImage(file);
});
}
e.target.value = '';
},
createImage(file) {
let reader = new FileReader();
let fileNameSegments = file.name.split('.');
let fileName = fileNameSegments[0];
let fileExtension = fileNameSegments[1];
let validExtnesions = ['jpg', 'png', 'gif'];
let placeholderImage = window.location.protocol + '//' + window.location.host + '/' + 'img/site/default/placeholder-image.png';
let primary = (this.images.length == 0) ? true : false;
reader.onload = (e) => {
let image = ($.inArray(fileExtension, validExtnesions) == -1) ? placeholderImage : e.target.result;
let data = {
name: fileName,
extension: fileExtension,
source: image,
description: null,
primary: primary,
image_directory: null,
};
this.$set(this.images, this.images.length, data);
}
reader.readAsDataURL(file);
},
}
}
Child Compononet (v-image):
export default {
props: ['_imgKey', '_image', '_errors'],
data() {
return {
form: {
id: _.clone(this._image.id),
name: _.clone(this._image.name),
description: _.clone(this._image.description),
primary: _.clone(this._image.primary),
extension: _.clone(this._image.extension),
image_directory: _.clone(this._image.image_directory),
source: _.clone(this._image.source),
},
}
},
watch: {
_image: {
handler(value) {
console.log('_image watch', this._imgKey, value.primary);
this.form.id = _.clone(value.id);
this.form.name = _.clone(value.name);
this.form.primary = _.clone(value.primary);
this.form.source = _.clone(value.source);
this.form.image_directory = _.clone(value.image_directory);
}, deep: true
}
},
methods: {
updatePrimary() {
this.form.primary = true;
this.updateImage();
},
updateImage() {
this.$emit('updateImage', {key: this._imgKey, form: this.form});
},
removeImage() {
this.$emit('removeImage', this._imgKey);
}
}
}
Update
I have been watching the vue developer tools for any changes to the image array. I push the primary button on the false image in the component this emits to the parent and calls the updateImage method. The first and second reset and update works, and changes the values. The issue has been tracked to: The 2nd 'after update' (true,false) does not match the third 'before reset'(true,true).
I made the previous changes mensioned in the comments and added a clone deep to both components data to prevent odd reactivity behaviour.
I checked the event log: 3x UpdateImage $emit by <VImage> which was expected.
Note: I moved the previous reset logic into the resetPrimary() method.
updateImage(request) {
console.log('update', request.key, request.form.primary);
console.log('b4 reset', this.images[0].primary, this.images[1].primary);
this.resetPrimary(request);
console.log('after reset', this.images[0].primary, this.images[1].primary);
this.$set(this.images, request.key, request.form);
console.log('after update', this.images[0].primary, this.images[1].primary);
},
output:
//First click - Image 1 (Expected)
update 1 true
b4 reset true false
after reset false false
after update false true
//Second click - Image 0 (Expected)
update 0 true
b4 reset false true
after reset false false
after update true false
//Third click - Image 1 (What?)
update 1 true
b4 reset true true //should be true false
after reset true true
after update true true
It appears that when attempting to update the same image a second time it somehow ignores the fact it has previously been reset to false.
I am having a problem setting dynamic image paths with Vue.js. I am using the Vue-Cli to build the project.
I believe the issue is caused because I am referencing image paths dynamically after runtime. Normally it seems the references to my ./assets/ folder are converted into ./img/ after runtime. Since I am changing the url dynamically after load the paths don't appear to work/load. Country is initially set via a store getters but is then v-modeled from a language select dropdown, where the values correspond the the url suffix.
<div id="flag-container" :style="{ backgroundImage: `url(${src})` }"></div>
computed: {
src(){
return `./assets/flags/flag-${this.country}.png`;
}
},
data() {
return {
country: this.$store.getters.language
}
}
Inspector shows url change is implemented.
Any recommendation on the best solution for this?
Using webpack require context and beforeMount, I was able to store the images in base64 format inside an object. I stored the object and accessed it with a dynamic key. Thanks Max for leading me to the right documentation.
export default {
beforeMount() {
var that = this;
function importAll(r) {
r.keys().forEach((key) => (that.imgCache[key] = r(key)));
}
importAll(require.context("../assets/flags/", true, /\.png$/));
},
computed: {
src() {
var key = `./flag-${this.country}.png`,
url = this.imgCache[key];
return url;
},
},
};
Don't use
data() {
return {
country: this.$store.getters.language
}
}
as it will stop being reactive to store changes. Use computed property
<div id="flag-container" :style="{ backgroundImage: `url(${src})` }"></div>
computed: {
src(){
return `./assets/flags/flag-${this.country}.png`;
},
country() {
return this.$store.getters.language
}
},