Habilitar GA4 y/o TagManager en PWAStudio
Como ya sabemos, PWA Studio y Magento, se comunican gracias al recurso UPWARD, separando por completo lo que es Magento, dejándolo como servidor, de la PWA como Headless para el cliente, con lo cual, las restricciones de librerías externas y la seguridad correrá por cuenta de la PWA.
¿Que ocurre?
Para ello, la PWA Studio, dispone de una extensión, insertada en su propio package, llamada upward-security-headers
. En la que podemos ver el siguiente fichero upward.yml
En pocas palabras, aquí lo importante en este caso sería esto:
veniaSecurityHeaders:
resolver: inline
inline:
content-security-policy:
template:
resolver: conditional
when:
- matches: env.SCRIPT_NAME
pattern: '.*\.php$'
use:
inline: "
script-src http: https: {{ backend }}{{#pageTypeNonce}} 'nonce-{{ pageTypeNonce }}'{{/pageTypeNonce}};
style-src 'self' blob: https: 'unsafe-inline' {{ backend }};
img-src data: http: https:;
object-src 'none';
base-uri 'none';
child-src 'self';
font-src 'self' fonts.gstatic.com;
frame-src assets.braintreegateway.com *.google.com *.youtube.com *.youtu.be *.vimeo.com
"
default:
inline: "
script-src http: https: {{ backend }};
style-src 'self' blob: https: 'unsafe-inline' {{ backend }};
img-src data: http: https:;
object-src 'none';
base-uri 'none';
child-src 'self';
font-src 'self' fonts.gstatic.com;
frame-src assets.braintreegateway.com *.google.com *.youtube.com *.youtu.be *.vimeo.com
Bien podemos ver aquí, que dan permisos a la inserción de script-src
solo a nuestro Backend (al magento2).
¿Cómo solucionamos esto?
En nuestro proyecto debemos de tener un local-intercept.js
, si no es el caso, os recomiendo echar un vistazo a esta parte de la doc de Magento Targets and Targetables.
Pero, lo normal es tener un interceptor en nuestro proyecto, podemos ver la ruta de este fichero en el package.json
, que es donde se tuvo que haber definido.
En el local-intercept.js
debemos añadir la siguiente función js:
...
function addCspSecurity(targets) {
const builtins = targets.of('@magento/pwa-buildpack');
builtins.transformUpward.tapPromise(async definitions => {
if (!definitions['customSecurityHeaders']) {
throw new Error(
`${
targets.name
} could not find its own definition in the emitted upward.yml`
);
}
const veniaSecurityHeaders = definitions.veniaSecurityHeaders.inline;
const securityHeaders = definitions['customSecurityHeaders'].inline;
for (const name of Object.keys(securityHeaders)) {
veniaSecurityHeaders[name] = `${'customSecurityHeaders'}.${name}`;
}
});
}
...
module.exports = (targets) => {
...
addCspSecurity(targets);
...
};
Este método, básicamente, lo que estaría haciendo es, sustituir el veniaSecurityHeaders
de la extensión de la PWAStudio por nuestros propios parámetros de seguridad.
Después de esto, actualizaremos el upward.yml
de nuestro proyecto, añadiendo justamente, el nombre que le hayamos dado anteriormente, en mi caso lo he llamado customSecurityHeaders
:
...
customSecurityHeaders:
resolver: inline
inline:
content-security-policy:
resolver: template
engine: mustache
provide:
backend: env.MAGENTO_BACKEND_URL
pageTypeNonce: veniaPageTypeNonce.nonce
template:
resolver: conditional
when:
- matches: env.NODE_ENV
pattern: development
use:
inline: ""
- matches: env.SCRIPT_NAME
pattern: '.*\.php$'
use:
inline: "
script-src http: https: 'unsafe-inline' *.googletagmanager.com *.google-analytics.com {{ backend }}{{#pageTypeNonce}} 'nonce-{{ pageTypeNonce }}'{{/pageTypeNonce}};
style-src 'self' blob: https: 'unsafe-inline' {{ backend }};
object-src 'none';
base-uri 'none';
child-src 'self';
font-src 'self' fonts.gstatic.com;
frame-src assets.braintreegateway.com *.google.com *.youtube.com *.youtu.be *.vimeo.com;
img-src http: https: *.googletagmanager.com *.google-analytics.com;
connect-src 'self' *.googletagmanager.com *.google-analytics.com *.analytics.google.com
"
default:
inline: "
script-src http: https: 'unsafe-inline' *.googletagmanager.com *.google-analytics.com {{ backend }};
style-src 'self' blob: https: 'unsafe-inline' {{ backend }};
object-src 'none';
base-uri 'none';
child-src 'self';
font-src 'self' fonts.gstatic.com;
frame-src assets.braintreegateway.com *.google.com *.youtube.com *.youtu.be *.vimeo.com;
img-src http: https: *.googletagmanager.com *.google-analytics.com;
connect-src 'self' *.googletagmanager.com *.google-analytics.com *.analytics.google.com
"
strict-transport-security:
inline: max-age=31536000
x-content-type-options:
inline: nosniff
x-frame-options:
inline: SAMEORIGIN
x-xss-protection:
inline: '1; mode=block'
...
Resultado
Después de hacer esto, el resultado que deberíamos ver, es cómo se ejecutan los scripts de analítica y gtm en el proyecto, así como poder tener acceso a los datos de navegación.
Gracias por leer este artículo!