@saulwade/swl-ses 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +238 -0
- package/README.md +560 -0
- package/_userland/agentes/.gitkeep +0 -0
- package/_userland/habilidades/.gitkeep +0 -0
- package/agentes/.evolved.json +9 -0
- package/agentes/accesibilidad-wcag-swl.md +692 -0
- package/agentes/arquitecto-swl.md +238 -0
- package/agentes/auto-evolucion-swl.md +854 -0
- package/agentes/backend-api-swl.md +470 -0
- package/agentes/backend-csharp-swl.md +418 -0
- package/agentes/backend-go-swl.md +388 -0
- package/agentes/backend-java-swl.md +279 -0
- package/agentes/backend-node-swl.md +477 -0
- package/agentes/backend-python-swl.md +608 -0
- package/agentes/backend-rust-swl.md +362 -0
- package/agentes/backend-workers-swl.md +480 -0
- package/agentes/cloud-infra-swl.md +485 -0
- package/agentes/consolidador-swl.md +539 -0
- package/agentes/datos-swl.md +584 -0
- package/agentes/depurador-swl.md +349 -0
- package/agentes/devops-ci-swl.md +374 -0
- package/agentes/disenador-ui-swl.md +558 -0
- package/agentes/documentador-swl.md +343 -0
- package/agentes/evals/arquitecto-swl.evals.json +56 -0
- package/agentes/evals/auto-evolucion-swl.evals.json +68 -0
- package/agentes/evals/implementador-swl.evals.json +56 -0
- package/agentes/evals/orquestador-swl.evals.json +60 -0
- package/agentes/evals/perfilador-usuario-swl.evals.json +60 -0
- package/agentes/evals/red-team-swl.evals.json +59 -0
- package/agentes/evals/revisor-codigo-swl.evals.json +59 -0
- package/agentes/frontend-angular-swl.md +627 -0
- package/agentes/frontend-css-swl.md +720 -0
- package/agentes/frontend-react-swl.md +696 -0
- package/agentes/frontend-swl.md +500 -0
- package/agentes/frontend-tailwind-swl.md +830 -0
- package/agentes/implementador-swl.md +328 -0
- package/agentes/investigador-swl.md +430 -0
- package/agentes/investigador-ux-swl.md +500 -0
- package/agentes/llm-apps-swl.md +276 -0
- package/agentes/migrador-swl.md +417 -0
- package/agentes/mobile-android-swl.md +509 -0
- package/agentes/mobile-cross-swl.md +539 -0
- package/agentes/mobile-ios-swl.md +500 -0
- package/agentes/mobile-testing-swl.md +300 -0
- package/agentes/notificador-swl.md +916 -0
- package/agentes/observabilidad-swl.md +436 -0
- package/agentes/orquestador-swl.md +884 -0
- package/agentes/pagos-swl.md +283 -0
- package/agentes/perfilador-usuario-swl.md +306 -0
- package/agentes/planificador-swl.md +402 -0
- package/agentes/producto-prd-swl.md +587 -0
- package/agentes/red-team-swl.md +216 -0
- package/agentes/release-manager-swl.md +568 -0
- package/agentes/rendimiento-swl.md +714 -0
- package/agentes/resolutor-build-swl.md +243 -0
- package/agentes/revisor-angular-swl.md +276 -0
- package/agentes/revisor-codigo-swl.md +348 -0
- package/agentes/revisor-csharp-swl.md +262 -0
- package/agentes/revisor-go-swl.md +257 -0
- package/agentes/revisor-java-swl.md +255 -0
- package/agentes/revisor-kotlin-swl.md +271 -0
- package/agentes/revisor-nextjs-swl.md +279 -0
- package/agentes/revisor-php-swl.md +269 -0
- package/agentes/revisor-react-swl.md +276 -0
- package/agentes/revisor-rust-swl.md +344 -0
- package/agentes/revisor-seguridad-swl.md +390 -0
- package/agentes/revisor-swift-swl.md +266 -0
- package/agentes/revisor-typescript-swl.md +344 -0
- package/agentes/sre-swl.md +265 -0
- package/agentes/tdd-qa-swl.md +354 -0
- package/agentes/ux-disenador-swl.md +501 -0
- package/bin/lib/bot-comandos.js +1030 -0
- package/bin/lib/bot-discovery.js +182 -0
- package/bin/lib/bot-git.js +142 -0
- package/bin/swl-ses.js +325 -0
- package/bin/swl-telegram-bot.js +442 -0
- package/bin/swl-telegram-bot.plist +21 -0
- package/bin/swl-telegram-bot.service +14 -0
- package/comandos/swl/.evolved.json +23 -0
- package/comandos/swl/actualizar.md +174 -0
- package/comandos/swl/adoptar-proyecto.md +207 -0
- package/comandos/swl/aprender.md +701 -0
- package/comandos/swl/auditar-deps.md +134 -0
- package/comandos/swl/autoresearch.md +170 -0
- package/comandos/swl/ayuda.md +224 -0
- package/comandos/swl/brainstorm.md +50 -0
- package/comandos/swl/checkpoint.md +330 -0
- package/comandos/swl/compactar.md +283 -0
- package/comandos/swl/configurar-ci.md +227 -0
- package/comandos/swl/contexto.md +112 -0
- package/comandos/swl/contribuir.md +233 -0
- package/comandos/swl/crear-skill.md +292 -0
- package/comandos/swl/cron.md +196 -0
- package/comandos/swl/dashboard.md +146 -0
- package/comandos/swl/discutir-fase.md +230 -0
- package/comandos/swl/ejecutar-fase.md +135 -0
- package/comandos/swl/evaluar-skill.md +487 -0
- package/comandos/swl/evolucion-estado.md +142 -0
- package/comandos/swl/evolucionar.md +259 -0
- package/comandos/swl/exportar-vault.md +189 -0
- package/comandos/swl/gateway.md +158 -0
- package/comandos/swl/inbox.md +116 -0
- package/comandos/swl/instalar.md +220 -0
- package/comandos/swl/instintos.md +86 -0
- package/comandos/swl/mapear-codebase.md +312 -0
- package/comandos/swl/mcp-status.md +175 -0
- package/comandos/swl/metricas.md +270 -0
- package/comandos/swl/modelo.md +102 -0
- package/comandos/swl/notificaciones.md +396 -0
- package/comandos/swl/nuevo-proyecto.md +154 -0
- package/comandos/swl/planear-fase.md +221 -0
- package/comandos/swl/plugins.md +256 -0
- package/comandos/swl/reflect-skills.md +125 -0
- package/comandos/swl/release.md +217 -0
- package/comandos/swl/revisar-impacto.md +206 -0
- package/comandos/swl/revisar.md +330 -0
- package/comandos/swl/salud.md +363 -0
- package/comandos/swl/sesiones.md +200 -0
- package/comandos/swl/skill-search.md +113 -0
- package/comandos/swl/verificar.md +585 -0
- package/comandos/swl/wiki.md +620 -0
- package/contextos/dev.md +32 -0
- package/contextos/research.md +30 -0
- package/contextos/review.md +31 -0
- package/habilidades/accesibilidad-a11y/SKILL.md +201 -0
- package/habilidades/accesibilidad-a11y/evals/evals.json +56 -0
- package/habilidades/accesibilidad-a11y/recursos/ejemplos-y-checklist-completo.md +441 -0
- package/habilidades/agent-browser/SKILL.md +218 -0
- package/habilidades/agentes-como-servicio/SKILL.md +218 -0
- package/habilidades/ai-runtime-security/SKILL.md +273 -0
- package/habilidades/angular-avanzado/SKILL.md +164 -0
- package/habilidades/angular-avanzado/recursos/ejemplos-avanzados.md +219 -0
- package/habilidades/angular-moderno/SKILL.md +186 -0
- package/habilidades/angular-moderno/evals/evals.json +45 -0
- package/habilidades/angular-moderno/recursos/ejemplos-avanzados.md +106 -0
- package/habilidades/api-rest-diseno/SKILL.md +191 -0
- package/habilidades/api-rest-diseno/recursos/openapi-template.yaml +506 -0
- package/habilidades/api-rest-diseno/recursos/referencia-api.md +140 -0
- package/habilidades/aprendizaje-continuo/SKILL.md +151 -0
- package/habilidades/aprendizaje-continuo/evals/evals.json +53 -0
- package/habilidades/aprendizaje-continuo/recursos/referencia-instintos.md +290 -0
- package/habilidades/async-python/SKILL.md +149 -0
- package/habilidades/async-python/evals/evals.json +47 -0
- package/habilidades/async-python/recursos/patrones-y-ejemplos-completos.md +292 -0
- package/habilidades/auth-patrones/.evolved.json +9 -0
- package/habilidades/auth-patrones/SKILL.md +413 -0
- package/habilidades/auth-patrones/recursos/implementaciones-completas.md +229 -0
- package/habilidades/auto-evolucion-protocolo/SKILL.md +276 -0
- package/habilidades/auto-evolucion-protocolo/evals/evals.json +55 -0
- package/habilidades/auto-evolucion-protocolo/recursos/referencia-completa.md +145 -0
- package/habilidades/autoresearch/SKILL.md +268 -0
- package/habilidades/autoresearch/evals/evals.json +41 -0
- package/habilidades/autoresearch/recursos/checklist-template.md +191 -0
- package/habilidades/autoresearch/scripts/calcular-score.js +88 -0
- package/habilidades/azure-cloud/SKILL.md +308 -0
- package/habilidades/azure-cloud/recursos/aks.md +327 -0
- package/habilidades/backend-mcp-servidor/SKILL.md +270 -0
- package/habilidades/backend-production-resilience/SKILL.md +288 -0
- package/habilidades/brainstorming/SKILL.md +295 -0
- package/habilidades/brainstorming/recursos/componentes-html.md +247 -0
- package/habilidades/build-errors-cpp/SKILL.md +270 -0
- package/habilidades/build-errors-csharp/SKILL.md +265 -0
- package/habilidades/build-errors-go/SKILL.md +306 -0
- package/habilidades/build-errors-java/SKILL.md +278 -0
- package/habilidades/build-errors-kotlin/SKILL.md +303 -0
- package/habilidades/build-errors-nextjs/SKILL.md +312 -0
- package/habilidades/build-errors-php/SKILL.md +270 -0
- package/habilidades/build-errors-python/SKILL.md +292 -0
- package/habilidades/build-errors-rust/SKILL.md +284 -0
- package/habilidades/build-errors-swift/SKILL.md +272 -0
- package/habilidades/build-errors-typescript/SKILL.md +369 -0
- package/habilidades/checklist-calidad/SKILL.md +271 -0
- package/habilidades/checklist-calidad/recursos/quality-report-template.md +148 -0
- package/habilidades/checklist-seguridad/SKILL.md +285 -0
- package/habilidades/checkpoints-verificacion/SKILL.md +298 -0
- package/habilidades/checkpoints-verificacion/recursos/checkpoint-templates.md +360 -0
- package/habilidades/ci-cd-pipelines/SKILL.md +157 -0
- package/habilidades/ci-cd-pipelines/recursos/github-actions-template.yaml +403 -0
- package/habilidades/ci-cd-pipelines/recursos/pipelines-completos.md +487 -0
- package/habilidades/cloud-aws/SKILL.md +142 -0
- package/habilidades/cloud-aws/recursos/servicios-aws-referencia.md +321 -0
- package/habilidades/compactacion-contexto/SKILL.md +247 -0
- package/habilidades/contenedores-docker/SKILL.md +137 -0
- package/habilidades/contenedores-docker/recursos/dockerfile-template.dockerfile +160 -0
- package/habilidades/contenedores-docker/recursos/ejemplos-y-configuraciones.md +327 -0
- package/habilidades/context-builder/SKILL.md +170 -0
- package/habilidades/control-profundidad/SKILL.md +128 -0
- package/habilidades/csharp-experto/SKILL.md +322 -0
- package/habilidades/csharp-patrones/SKILL.md +316 -0
- package/habilidades/csharp-testing/SKILL.md +286 -0
- package/habilidades/css-moderno/SKILL.md +166 -0
- package/habilidades/css-moderno/evals/evals.json +43 -0
- package/habilidades/css-moderno/recursos/ejemplos-y-patrones-completos.md +337 -0
- package/habilidades/datos-etl/SKILL.md +129 -0
- package/habilidades/datos-etl/recursos/implementaciones-completas.md +322 -0
- package/habilidades/dbml-experto/SKILL.md +339 -0
- package/habilidades/dbml-experto/evals/evals.json +56 -0
- package/habilidades/dependencias-auditoria/SKILL.md +320 -0
- package/habilidades/deprecacion-migracion/SKILL.md +169 -0
- package/habilidades/deprecacion-migracion/recursos/implementaciones-completas.md +220 -0
- package/habilidades/design-tokens/SKILL.md +158 -0
- package/habilidades/design-tokens/recursos/tokens-y-configuracion.md +363 -0
- package/habilidades/devsecops-pipeline-security/SKILL.md +309 -0
- package/habilidades/diagrama-arquitectura/SKILL.md +165 -0
- package/habilidades/diagrama-arquitectura/assets/template.html +276 -0
- package/habilidades/discutir-fase/SKILL.md +188 -0
- package/habilidades/diseno-herramientas-agente/SKILL.md +199 -0
- package/habilidades/diseno-responsivo/SKILL.md +186 -0
- package/habilidades/diseno-responsivo/recursos/ejemplos-layouts.md +156 -0
- package/habilidades/django-experto/SKILL.md +205 -0
- package/habilidades/django-experto/recursos/async-django.md +390 -0
- package/habilidades/django-experto/recursos/drf-patrones.md +438 -0
- package/habilidades/django-experto/recursos/orm-avanzado.md +382 -0
- package/habilidades/django-experto/recursos/referencia-completa.md +188 -0
- package/habilidades/django-experto/recursos/testing-django.md +415 -0
- package/habilidades/doc-sync/SKILL.md +280 -0
- package/habilidades/drift-detection/SKILL.md +179 -0
- package/habilidades/ejecutar-fase/SKILL.md +468 -0
- package/habilidades/estilo-sin-ai-isms/SKILL.md +775 -0
- package/habilidades/estilo-sin-ai-isms/evals/evals.json +63 -0
- package/habilidades/estilo-sin-ai-isms/scripts/detectar_aiisms.py +500 -0
- package/habilidades/estructura-proyecto-claude/SKILL.md +215 -0
- package/habilidades/estructura-proyecto-claude/recursos/claude-md-template.md +261 -0
- package/habilidades/estructura-proyecto-claude/recursos/configuracion-y-extensiones.md +176 -0
- package/habilidades/estructura-proyecto-claude/recursos/frontmatter-y-hooks-referencia.md +289 -0
- package/habilidades/estructura-proyecto-claude/recursos/mcp-json-template.json +77 -0
- package/habilidades/estructura-proyecto-claude/recursos/variantes-por-stack.md +177 -0
- package/habilidades/evaluacion-agentes/SKILL.md +314 -0
- package/habilidades/event-driven/SKILL.md +153 -0
- package/habilidades/event-driven/recursos/implementaciones-completas.md +423 -0
- package/habilidades/extraccion-documentos/SKILL.md +221 -0
- package/habilidades/extractor-de-aprendizajes/.evolved.json +9 -0
- package/habilidades/extractor-de-aprendizajes/SKILL.md +311 -0
- package/habilidades/extractor-de-aprendizajes/evals/evals.json +55 -0
- package/habilidades/fastapi-experto/SKILL.md +221 -0
- package/habilidades/fastapi-experto/recursos/async-patterns.md +438 -0
- package/habilidades/fastapi-experto/recursos/dependency-injection.md +330 -0
- package/habilidades/fastapi-experto/recursos/referencia-completa.md +79 -0
- package/habilidades/fastapi-experto/recursos/testing-httpx.md +420 -0
- package/habilidades/filament-admin/SKILL.md +290 -0
- package/habilidades/frontend-avanzado/SKILL.md +257 -0
- package/habilidades/frontend-avanzado/recursos/apis-nativas-ejemplos.md +341 -0
- package/habilidades/gcp-cloud/SKILL.md +260 -0
- package/habilidades/gcp-cloud/recursos/gke.md +234 -0
- package/habilidades/gcp-cloud/recursos/terraform-gcp.md +307 -0
- package/habilidades/generacion-mermaid/SKILL.md +229 -0
- package/habilidades/git-worktrees-paralelo/SKILL.md +270 -0
- package/habilidades/go-experto/SKILL.md +305 -0
- package/habilidades/go-patrones/SKILL.md +299 -0
- package/habilidades/go-testing/SKILL.md +291 -0
- package/habilidades/graphql-experto/SKILL.md +323 -0
- package/habilidades/guardrail-semantico/SKILL.md +282 -0
- package/habilidades/harness-claude-code/SKILL.md +299 -0
- package/habilidades/iam-secretos/SKILL.md +265 -0
- package/habilidades/iam-secretos/recursos/implementaciones-completas.md +356 -0
- package/habilidades/infra-github-actions/SKILL.md +166 -0
- package/habilidades/instalar-sistema/.evolved.json +9 -0
- package/habilidades/instalar-sistema/SKILL.md +221 -0
- package/habilidades/java-experto/SKILL.md +290 -0
- package/habilidades/java-patrones/SKILL.md +275 -0
- package/habilidades/java-testing/SKILL.md +288 -0
- package/habilidades/kotlin-compose/SKILL.md +278 -0
- package/habilidades/kotlin-compose/recursos/animaciones-performance.md +93 -0
- package/habilidades/kotlin-experto/SKILL.md +318 -0
- package/habilidades/kotlin-testing/SKILL.md +267 -0
- package/habilidades/kotlin-testing/recursos/testing-avanzado.md +74 -0
- package/habilidades/kubernetes-orquestacion/SKILL.md +152 -0
- package/habilidades/kubernetes-orquestacion/recursos/manifiestos-completos.md +452 -0
- package/habilidades/langchain-langraph/SKILL.md +386 -0
- package/habilidades/langchain-langraph/recursos/evaluacion-rag.md +321 -0
- package/habilidades/langchain-langraph/recursos/rag-maturity-model.md +225 -0
- package/habilidades/langchain-langraph/recursos/vectorstores.md +306 -0
- package/habilidades/legacy-code-rescue/SKILL.md +267 -0
- package/habilidades/likec4-experto/SKILL.md +412 -0
- package/habilidades/likec4-experto/evals/evals.json +69 -0
- package/habilidades/manejo-errores/.evolved.json +9 -0
- package/habilidades/manejo-errores/SKILL.md +407 -0
- package/habilidades/manejo-errores/recursos/implementaciones-completas.md +248 -0
- package/habilidades/mapear-codebase/SKILL.md +275 -0
- package/habilidades/memoria-busqueda/SKILL.md +194 -0
- package/habilidades/memoria-busqueda/evals/evals.json +44 -0
- package/habilidades/meta-skills-estandar/SKILL.md +298 -0
- package/habilidades/meta-skills-estandar/recursos/anti-patrones-y-leyes.md +205 -0
- package/habilidades/meta-skills-estandar/recursos/frameworks-seguridad.md +107 -0
- package/habilidades/meta-skills-estandar/recursos/idiomas-framework.md +60 -0
- package/habilidades/meta-skills-estandar/recursos/skills-as-agents.md +163 -0
- package/habilidades/microservicios/SKILL.md +155 -0
- package/habilidades/microservicios/recursos/patrones-y-ejemplos-completos.md +325 -0
- package/habilidades/mobile-flutter/SKILL.md +199 -0
- package/habilidades/mobile-flutter/recursos/ejemplos-completos.md +319 -0
- package/habilidades/mobile-react-native/SKILL.md +176 -0
- package/habilidades/mobile-react-native/recursos/ejemplos-completos.md +216 -0
- package/habilidades/mongodb-experto/SKILL.md +302 -0
- package/habilidades/monitoring-alertas/SKILL.md +201 -0
- package/habilidades/monitoring-alertas/recursos/instrumentacion-y-alertas.md +301 -0
- package/habilidades/nestjs-experto/SKILL.md +307 -0
- package/habilidades/nestjs-experto/recursos/guards-interceptors.md +339 -0
- package/habilidades/nestjs-experto/recursos/modulos-di.md +287 -0
- package/habilidades/nestjs-experto/recursos/testing-nestjs.md +354 -0
- package/habilidades/nextjs-experto/SKILL.md +335 -0
- package/habilidades/nextjs-patrones/SKILL.md +303 -0
- package/habilidades/nextjs-testing/SKILL.md +331 -0
- package/habilidades/node-experto/.evolved.json +9 -0
- package/habilidades/node-experto/SKILL.md +266 -0
- package/habilidades/node-experto/recursos/patrones-completos.md +283 -0
- package/habilidades/notificaciones-multicanal/SKILL.md +159 -0
- package/habilidades/notificaciones-multicanal/recursos/config-template.json +115 -0
- package/habilidades/notificaciones-multicanal/recursos/configuracion-y-templates.md +303 -0
- package/habilidades/nuevo-proyecto/SKILL.md +204 -0
- package/habilidades/orquestacion-async/SKILL.md +303 -0
- package/habilidades/paid-media-tracking/SKILL.md +269 -0
- package/habilidades/paid-media-tracking/recursos/auditoria-tracking.md +220 -0
- package/habilidades/paid-media-tracking/recursos/google-ads-api.md +215 -0
- package/habilidades/patrones-python/SKILL.md +228 -0
- package/habilidades/patrones-python/evals/evals.json +56 -0
- package/habilidades/patrones-python/recursos/patrones-avanzados.md +469 -0
- package/habilidades/patrones-python/recursos/referencia-completa.md +202 -0
- package/habilidades/perfil-usuario/SKILL.md +200 -0
- package/habilidades/perfil-usuario/evals/evals.json +55 -0
- package/habilidades/performance-baseline/SKILL.md +297 -0
- package/habilidades/php-experto/SKILL.md +291 -0
- package/habilidades/php-patrones/SKILL.md +306 -0
- package/habilidades/php-testing/SKILL.md +280 -0
- package/habilidades/planear-fase/SKILL.md +269 -0
- package/habilidades/postgresql-experto/SKILL.md +151 -0
- package/habilidades/postgresql-experto/evals/evals.json +53 -0
- package/habilidades/postgresql-experto/recursos/referencia-completa.md +215 -0
- package/habilidades/prevencion-racionalizacion/SKILL.md +175 -0
- package/habilidades/prevencion-sobreingenieria/SKILL.md +323 -0
- package/habilidades/privacy-memoria/SKILL.md +141 -0
- package/habilidades/privacy-memoria/evals/evals.json +43 -0
- package/habilidades/prompt-engineering/SKILL.md +518 -0
- package/habilidades/prompt-engineering/recursos/patrones-avanzados.md +467 -0
- package/habilidades/rag-arquitectura/SKILL.md +338 -0
- package/habilidades/rails-experto/SKILL.md +237 -0
- package/habilidades/rails-experto/recursos/active-record.md +260 -0
- package/habilidades/rails-experto/recursos/hotwire-turbo.md +293 -0
- package/habilidades/rails-experto/recursos/testing-rspec.md +362 -0
- package/habilidades/react-experto/SKILL.md +209 -0
- package/habilidades/react-experto/evals/evals.json +55 -0
- package/habilidades/react-experto/recursos/patrones-y-ejemplos-completos.md +240 -0
- package/habilidades/react-optimizacion/SKILL.md +174 -0
- package/habilidades/react-optimizacion/recursos/patrones-avanzados.md +138 -0
- package/habilidades/redis-experto/SKILL.md +305 -0
- package/habilidades/release-semver/.evolved.json +9 -0
- package/habilidades/release-semver/SKILL.md +248 -0
- package/habilidades/release-semver/scripts/generar-changelog.sh +238 -0
- package/habilidades/rust-experto/SKILL.md +400 -0
- package/habilidades/rust-patrones/SKILL.md +296 -0
- package/habilidades/rust-testing/SKILL.md +311 -0
- package/habilidades/seguridad-skills-ia/SKILL.md +262 -0
- package/habilidades/sql-optimizacion/SKILL.md +200 -0
- package/habilidades/sql-optimizacion/evals/evals.json +54 -0
- package/habilidades/sql-optimizacion/recursos/patrones-sql-avanzados.md +131 -0
- package/habilidades/sre-patrones/SKILL.md +333 -0
- package/habilidades/sre-patrones/recursos/chaos-engineering.md +241 -0
- package/habilidades/sre-patrones/recursos/oncall-design.md +236 -0
- package/habilidades/stripe-pagos/SKILL.md +550 -0
- package/habilidades/stripe-pagos/recursos/errores-reintentos.md +390 -0
- package/habilidades/stripe-pagos/recursos/stripe-connect.md +290 -0
- package/habilidades/structured-outputs/SKILL.md +343 -0
- package/habilidades/swift-experto/SKILL.md +320 -0
- package/habilidades/swift-experto/recursos/keychain-y-wrappers.md +110 -0
- package/habilidades/swift-patrones/SKILL.md +313 -0
- package/habilidades/swift-patrones/recursos/tca-ejemplo-completo.md +113 -0
- package/habilidades/swift-testing/SKILL.md +254 -0
- package/habilidades/swift-testing/recursos/xcuitest-planes.md +143 -0
- package/habilidades/swl-dashboard/SKILL.md +370 -0
- package/habilidades/swl-markitdown/SKILL.md +285 -0
- package/habilidades/swl-markitdown/evals/evals.json +52 -0
- package/habilidades/swl-revisar-impacto/SKILL.md +233 -0
- package/habilidades/tailwind-experto/SKILL.md +240 -0
- package/habilidades/tailwind-experto/recursos/referencia-completa.md +184 -0
- package/habilidades/tdd-workflow/SKILL.md +293 -0
- package/habilidades/terraform-experto/SKILL.md +321 -0
- package/habilidades/testing-python/SKILL.md +340 -0
- package/habilidades/testing-python/recursos/ejemplos-completos.md +167 -0
- package/habilidades/threat-model-lite/SKILL.md +246 -0
- package/habilidades/tracing-processor/SKILL.md +212 -0
- package/habilidades/tracking-measurement/SKILL.md +239 -0
- package/habilidades/tracking-measurement/recursos/consent-mode.md +231 -0
- package/habilidades/tracking-measurement/recursos/gtm-datalayer.md +216 -0
- package/habilidades/tracking-measurement/recursos/meta-capi.md +262 -0
- package/habilidades/typescript-avanzado/SKILL.md +144 -0
- package/habilidades/typescript-avanzado/evals/evals.json +55 -0
- package/habilidades/typescript-avanzado/recursos/patrones-y-ejemplos-completos.md +298 -0
- package/habilidades/typescript-diagnosticos/SKILL.md +513 -0
- package/habilidades/ux-diseno/SKILL.md +116 -0
- package/habilidades/ux-diseno/evals/evals.json +43 -0
- package/habilidades/ux-diseno/recursos/patrones-ux-referencia.md +214 -0
- package/habilidades/validacion-ci-sistema/SKILL.md +136 -0
- package/habilidades/validacion-ci-sistema/recursos/validadores-completos.md +369 -0
- package/habilidades/validacion-ci-sistema/scripts/validar-sistema.sh +286 -0
- package/habilidades/verificacion-evidencia/SKILL.md +160 -0
- package/habilidades/verificar-trabajo/SKILL.md +303 -0
- package/habilidades/verificar-trabajo/recursos/plantilla-verificacion.md +60 -0
- package/habilidades/wiki-conocimiento/SKILL.md +276 -0
- package/habilidades/wireframes-flujos/SKILL.md +212 -0
- package/habilidades/wireframes-flujos/recursos/referencia-completa.md +192 -0
- package/habilidades/workflow-claude-code/SKILL.md +260 -0
- package/habilidades/workflow-claude-code/recursos/referencia-completa.md +109 -0
- package/hooks/_run-hook.sh +57 -0
- package/hooks/actualizar-perfil-usuario.js +364 -0
- package/hooks/agente-lifecycle.js +71 -0
- package/hooks/aiisms-detector.js +173 -0
- package/hooks/audit-trail.js +204 -0
- package/hooks/auto-background.js +97 -0
- package/hooks/auto-consolidacion.js +178 -0
- package/hooks/auto-evolucion.js +666 -0
- package/hooks/auto-restaurar-settings.js +360 -0
- package/hooks/calidad-pre-commit.js +929 -0
- package/hooks/calidad-typescript.js +511 -0
- package/hooks/captura-feedback-usuario.js +148 -0
- package/hooks/check-update.js +211 -0
- package/hooks/clasificador-mensajes.js +271 -0
- package/hooks/degradacion-instintos.js +272 -0
- package/hooks/escaneo-secretos.js +389 -0
- package/hooks/extraccion-aprendizajes.js +763 -0
- package/hooks/grafo-contexto.js +129 -0
- package/hooks/graph-update.js +67 -0
- package/hooks/guardrail-modelo.js +247 -0
- package/hooks/inbox-aviso.js +75 -0
- package/hooks/inyeccion-contexto.js +246 -0
- package/hooks/lib/abort-registry.js +214 -0
- package/hooks/lib/agent-backend.js +210 -0
- package/hooks/lib/agent-comms.js +263 -0
- package/hooks/lib/agent-issue-codes.js +284 -0
- package/hooks/lib/agent-matcher.js +189 -0
- package/hooks/lib/async-hook-registry.js +252 -0
- package/hooks/lib/atomic-write.js +130 -0
- package/hooks/lib/auto-consolidator.js +335 -0
- package/hooks/lib/canary-skills.js +187 -0
- package/hooks/lib/consolidation-lock.js +291 -0
- package/hooks/lib/context-builder.js +430 -0
- package/hooks/lib/context-compressor.js +657 -0
- package/hooks/lib/convergence-detector.js +105 -0
- package/hooks/lib/delegation-tracker.js +198 -0
- package/hooks/lib/detectar-package-manager.js +423 -0
- package/hooks/lib/edit-accumulator.js +171 -0
- package/hooks/lib/error-classifier.js +308 -0
- package/hooks/lib/event-bus.js +112 -0
- package/hooks/lib/evolution-tracker.js +442 -0
- package/hooks/lib/execution-state.js +316 -0
- package/hooks/lib/fingerprint-id.js +135 -0
- package/hooks/lib/gateway-notify.js +116 -0
- package/hooks/lib/graph-security.js +75 -0
- package/hooks/lib/guardrail-metrics.js +202 -0
- package/hooks/lib/hook-circuit-breaker.js +206 -0
- package/hooks/lib/loop-detector.js +267 -0
- package/hooks/lib/mcp-health.js +184 -0
- package/hooks/lib/mcp-pool.js +436 -0
- package/hooks/lib/memory-search.js +506 -0
- package/hooks/lib/merkle-audit.js +96 -0
- package/hooks/lib/model-router.js +222 -0
- package/hooks/lib/normalize-error.js +324 -0
- package/hooks/lib/normalize-input.js +65 -0
- package/hooks/lib/nudge-tracker.js +306 -0
- package/hooks/lib/otlp-exporter.js +365 -0
- package/hooks/lib/performance-marks.js +239 -0
- package/hooks/lib/privacy-filter.js +128 -0
- package/hooks/lib/prompt-injection-scanner.js +209 -0
- package/hooks/lib/provenance-tracker.js +183 -0
- package/hooks/lib/rate-limit-tracker.js +253 -0
- package/hooks/lib/reflect-classifier.js +164 -0
- package/hooks/lib/resource-quota.js +122 -0
- package/hooks/lib/retry-jitter.js +165 -0
- package/hooks/lib/risk-engine.js +368 -0
- package/hooks/lib/run-log.js +408 -0
- package/hooks/lib/session-fts.js +379 -0
- package/hooks/lib/session-store.js +293 -0
- package/hooks/lib/singleton-guard.js +159 -0
- package/hooks/lib/skill-auditor.js +588 -0
- package/hooks/lib/sync-status.js +228 -0
- package/hooks/lib/taint-tracker.js +107 -0
- package/hooks/lib/task-service.js +295 -0
- package/hooks/lib/tech-skills-map.js +146 -0
- package/hooks/lib/telegram-cliente.js +159 -0
- package/hooks/lib/telegram-config.js +170 -0
- package/hooks/lib/token-budget.js +156 -0
- package/hooks/lib/token-estimator.js +420 -0
- package/hooks/lib/toon-compressor.js +245 -0
- package/hooks/lib/usage-model.js +183 -0
- package/hooks/lib/variable-resolver.js +230 -0
- package/hooks/linea-estado.js +324 -0
- package/hooks/metricas-evolucion.js +209 -0
- package/hooks/monitor-contexto.js +325 -0
- package/hooks/notificacion-sesion-stop.js +198 -0
- package/hooks/notificacion-telegram-notification.js +4 -0
- package/hooks/notificacion-telegram-subagent.js +4 -0
- package/hooks/notificacion-telegram.js +267 -0
- package/hooks/preservar-estado-pre-compact.js +150 -0
- package/hooks/proteccion-rutas.js +366 -0
- package/hooks/registro-turnos.js +209 -0
- package/hooks/resumen-sesion.js +249 -0
- package/hooks/risk-scoring.js +323 -0
- package/hooks/rotar-audit-auto.js +122 -0
- package/hooks/sugerir-regenerar-inventario.js +170 -0
- package/hooks/telemetria-agentes.js +167 -0
- package/hooks/tracking-costos.js +688 -0
- package/instintos/global.yaml +8 -0
- package/instintos/perfil-usuario.yaml +53 -0
- package/instintos/prompt-appendices.yaml +57 -0
- package/instintos/proyecto.yaml +372 -0
- package/manifiestos/gateway-config.json +77 -0
- package/manifiestos/handoff-context.json +223 -0
- package/manifiestos/hook-profiles.json +44 -0
- package/manifiestos/hooks-config.json +360 -0
- package/manifiestos/modulos.json +1173 -0
- package/manifiestos/perfiles.json +404 -0
- package/package.json +86 -0
- package/plantillas/ESTADO.md +109 -0
- package/plantillas/HOJA-RUTA.md +143 -0
- package/plantillas/PROYECTO.md +122 -0
- package/plantillas/REQUISITOS.md +132 -0
- package/plantillas/auditor-veto-template.md +105 -0
- package/plantillas/github-workflows/README.md +47 -0
- package/plantillas/github-workflows/release-please.yml +44 -0
- package/plantillas/github-workflows/swl-ci.yml +107 -0
- package/plantillas/github-workflows/swl-security.yml +51 -0
- package/plantillas/mcp-mineru.json +13 -0
- package/plantillas/research/ARQUITECTURA.md +220 -0
- package/plantillas/research/FUNCIONALIDADES.md +175 -0
- package/plantillas/research/RESUMEN.md +165 -0
- package/plantillas/research/STACK.md +233 -0
- package/plantillas/research/TRAMPAS.md +299 -0
- package/plantillas/skill-evals-template.json +44 -0
- package/plugin.json +343 -0
- package/reglas/accesibilidad.md +269 -0
- package/reglas/api-diseno.md +400 -0
- package/reglas/arquitectura.md +352 -0
- package/reglas/brevedad-output.md +124 -0
- package/reglas/cloud-infra.md +247 -0
- package/reglas/docs.md +245 -0
- package/reglas/estilo-codigo.md +201 -0
- package/reglas/git-workflow.md +245 -0
- package/reglas/gobernanza.md +271 -0
- package/reglas/harness-claude-code.md +213 -0
- package/reglas/hooks.md +186 -0
- package/reglas/lenguajes/csharp/estilo-codigo.md +231 -0
- package/reglas/lenguajes/csharp/hooks.md +281 -0
- package/reglas/lenguajes/csharp/patrones.md +226 -0
- package/reglas/lenguajes/csharp/seguridad.md +258 -0
- package/reglas/lenguajes/csharp/testing.md +176 -0
- package/reglas/lenguajes/go/estilo-codigo.md +195 -0
- package/reglas/lenguajes/go/hooks.md +249 -0
- package/reglas/lenguajes/go/patrones.md +249 -0
- package/reglas/lenguajes/go/seguridad.md +225 -0
- package/reglas/lenguajes/go/testing.md +272 -0
- package/reglas/lenguajes/java/estilo-codigo.md +217 -0
- package/reglas/lenguajes/java/hooks.md +251 -0
- package/reglas/lenguajes/java/patrones.md +226 -0
- package/reglas/lenguajes/java/seguridad.md +233 -0
- package/reglas/lenguajes/java/testing.md +238 -0
- package/reglas/lenguajes/kotlin/estilo-codigo.md +208 -0
- package/reglas/lenguajes/kotlin/hooks.md +245 -0
- package/reglas/lenguajes/kotlin/patrones.md +201 -0
- package/reglas/lenguajes/kotlin/seguridad.md +202 -0
- package/reglas/lenguajes/kotlin/testing.md +236 -0
- package/reglas/lenguajes/nextjs/estilo-codigo.md +175 -0
- package/reglas/lenguajes/nextjs/hooks.md +186 -0
- package/reglas/lenguajes/nextjs/patrones.md +225 -0
- package/reglas/lenguajes/nextjs/seguridad.md +216 -0
- package/reglas/lenguajes/nextjs/testing.md +193 -0
- package/reglas/lenguajes/php/estilo-codigo.md +228 -0
- package/reglas/lenguajes/php/hooks.md +165 -0
- package/reglas/lenguajes/php/patrones.md +233 -0
- package/reglas/lenguajes/php/seguridad.md +186 -0
- package/reglas/lenguajes/php/testing.md +205 -0
- package/reglas/lenguajes/rust/estilo-codigo.md +207 -0
- package/reglas/lenguajes/rust/hooks.md +240 -0
- package/reglas/lenguajes/rust/patrones.md +250 -0
- package/reglas/lenguajes/rust/seguridad.md +221 -0
- package/reglas/lenguajes/rust/testing.md +194 -0
- package/reglas/lenguajes/swift/estilo-codigo.md +238 -0
- package/reglas/lenguajes/swift/hooks.md +257 -0
- package/reglas/lenguajes/swift/patrones.md +235 -0
- package/reglas/lenguajes/swift/seguridad.md +248 -0
- package/reglas/lenguajes/swift/testing.md +242 -0
- package/reglas/markitdown.md +60 -0
- package/reglas/memoria-consolidada.md +209 -0
- package/reglas/patrones.md +225 -0
- package/reglas/performance.md +195 -0
- package/reglas/pruebas.md +159 -0
- package/reglas/seguridad-agentes.md +351 -0
- package/reglas/seguridad.md +151 -0
- package/reglas/skills-estandar.md +373 -0
- package/reglas/testing.md +193 -0
- package/schemas/agent-contract.json +176 -0
- package/schemas/agent-frontmatter.schema.json +149 -0
- package/schemas/agent-message.schema.json +53 -0
- package/schemas/agent-output-implementacion.schema.json +85 -0
- package/schemas/agent-output-planificacion.schema.json +113 -0
- package/schemas/agent-output-review.schema.json +78 -0
- package/schemas/diary-entry.schema.json +80 -0
- package/schemas/hook-profiles.schema.json +39 -0
- package/schemas/hooks-config.schema.json +74 -0
- package/schemas/instinct.schema.json +115 -0
- package/schemas/modulos.schema.json +29 -0
- package/schemas/perfiles.schema.json +28 -0
- package/schemas/plugin.schema.json +64 -0
- package/schemas/skill-evals.schema.json +95 -0
- package/schemas/skill-frontmatter.schema.json +170 -0
- package/scripts/actualizar.js +145 -0
- package/scripts/audit-skills.sh +78 -0
- package/scripts/auditar-agentes-gaps.js +149 -0
- package/scripts/auditar-cobertura-frameworks.js +241 -0
- package/scripts/auditar-skills-gaps.js +206 -0
- package/scripts/bootstrap-instintos.js +259 -0
- package/scripts/check-update.js +109 -0
- package/scripts/comandos/agents.js +105 -0
- package/scripts/comandos/info.js +108 -0
- package/scripts/comandos/install-asistido.js +186 -0
- package/scripts/comandos/skills.js +211 -0
- package/scripts/configurar-branch-protection.js +418 -0
- package/scripts/daemon-swl.py +388 -0
- package/scripts/desinstalar.js +130 -0
- package/scripts/doctor.js +559 -0
- package/scripts/field-report.js +199 -0
- package/scripts/generar-inventario.js +317 -0
- package/scripts/inbox-tmux-inject.js +161 -0
- package/scripts/inferir-herramientas-permitidas.js +586 -0
- package/scripts/inicializar.js +133 -0
- package/scripts/instalador.js +1031 -0
- package/scripts/instalar-git-hook.js +122 -0
- package/scripts/lib/agp-frontmatter.js +222 -0
- package/scripts/lib/append-con-marcadores.js +199 -0
- package/scripts/lib/artefactos-python.js +43 -0
- package/scripts/lib/audit-query.js +221 -0
- package/scripts/lib/autostart-linux.js +347 -0
- package/scripts/lib/autostart-macos.js +360 -0
- package/scripts/lib/autostart-windows.js +307 -0
- package/scripts/lib/budget-enforcer.js +252 -0
- package/scripts/lib/claude-sessions.js +285 -0
- package/scripts/lib/configurar-ci.js +380 -0
- package/scripts/lib/console-span-exporter.js +92 -0
- package/scripts/lib/contadores-inventario.js +217 -0
- package/scripts/lib/dashboard-widgets.js +290 -0
- package/scripts/lib/detectar-runtime.js +279 -0
- package/scripts/lib/detectar-stack.js +187 -0
- package/scripts/lib/diary-entry.js +234 -0
- package/scripts/lib/drift-detector.js +545 -0
- package/scripts/lib/estado.js +124 -0
- package/scripts/lib/gestor-componentes.js +243 -0
- package/scripts/lib/gitignore-manifest.js +305 -0
- package/scripts/lib/graph-analyze.py +556 -0
- package/scripts/lib/graph-builder.py +485 -0
- package/scripts/lib/graph-cluster.py +259 -0
- package/scripts/lib/health-row.js +168 -0
- package/scripts/lib/hooks-settings.js +789 -0
- package/scripts/lib/manifiestos.js +138 -0
- package/scripts/lib/mc-client.js +137 -0
- package/scripts/lib/notificaciones-telegram.js +1107 -0
- package/scripts/lib/npm-version.js +261 -0
- package/scripts/lib/paquetes-conocidos.js +50 -0
- package/scripts/lib/preservar-usuario.js +586 -0
- package/scripts/lib/prompt-builder.js +264 -0
- package/scripts/lib/resolver-externo.js +332 -0
- package/scripts/lib/schedule-parser.js +305 -0
- package/scripts/lib/scoring-instintos.js +240 -0
- package/scripts/lib/seguridad.js +160 -0
- package/scripts/lib/selector-interactivo.js +152 -0
- package/scripts/lib/semantic-search.js +242 -0
- package/scripts/lib/skill-discovery.js +234 -0
- package/scripts/lib/skill-metrics.js +246 -0
- package/scripts/lib/skill-normalizer.js +112 -0
- package/scripts/lib/skills-hub.js +340 -0
- package/scripts/lib/span-schema.js +134 -0
- package/scripts/lib/tool-cost-analyzer.js +255 -0
- package/scripts/lib/tracing-processor-interface.js +286 -0
- package/scripts/lib/transformadores/base.js +80 -0
- package/scripts/lib/transformadores/claude.js +124 -0
- package/scripts/lib/transformadores/codex.js +115 -0
- package/scripts/lib/transformadores/copilot.js +106 -0
- package/scripts/lib/transformadores/gemini.js +74 -0
- package/scripts/lib/transformadores/index.js +35 -0
- package/scripts/lib/transformadores/opencode.js +75 -0
- package/scripts/lib/ui.js +259 -0
- package/scripts/limpiar-artefactos-python.js +131 -0
- package/scripts/mcp-orchestrator.py +386 -0
- package/scripts/mcp-pool-manager.py +352 -0
- package/scripts/mcp-telemetry.py +378 -0
- package/scripts/poblar-evolvable.js +226 -0
- package/scripts/publicar.js +287 -0
- package/scripts/reflect-skills.js +403 -0
- package/scripts/rotar-audit-logs.js +185 -0
- package/scripts/run-skill-evals.js +242 -0
- package/scripts/smoke-test.js +374 -0
- package/scripts/token-analysis.py +471 -0
- package/scripts/validar-manifest.js +195 -0
- package/scripts/validar-memoria.js +321 -0
- package/scripts/validar-tests-aislamiento.js +184 -0
- package/scripts/validar-tokens-test.js +208 -0
- package/scripts/validar.js +147 -0
- package/scripts/validate-markdown.py +339 -0
- package/scripts/validate-skills.py +385 -0
- package/scripts/vendor/claude-usage/README.md +116 -0
- package/scripts/vendor/claude-usage/cli.py +334 -0
- package/scripts/vendor/claude-usage/dashboard.py +795 -0
- package/scripts/vendor/claude-usage/scanner.py +467 -0
- package/scripts/vendor/markitdown/cli.py +194 -0
- package/scripts/verificar-evolucion.js +289 -0
- package/scripts/verificar-release.js +494 -0
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tracking-measurement
|
|
3
|
+
description: >
|
|
4
|
+
Implementación técnica de sistemas de medición web: GTM (dataLayer, triggers,
|
|
5
|
+
variables, tags), GA4 (eventos, e-commerce, dimensiones personalizadas), Meta
|
|
6
|
+
CAPI server-side con deduplicación, Enhanced Conversions y Consent Mode v2.
|
|
7
|
+
Cargar cuando se implemente conversion tracking, se configure GTM, se integre
|
|
8
|
+
GA4 o Meta Pixel, se construya un endpoint server-side para CAPI, o se
|
|
9
|
+
implemente cumplimiento de privacidad GDPR/CCPA en tracking.
|
|
10
|
+
version: "1.0.0"
|
|
11
|
+
herramientasPermitidas: [Read, Write]
|
|
12
|
+
evolvable: true # default para skill estandar
|
|
13
|
+
exclusiones:
|
|
14
|
+
- "No cargar para análisis de datos de conversiones ya capturados (reportes de ROAS, atribución multi-touch) — para análisis de datos de paid media cargar `paid-media-tracking`."
|
|
15
|
+
- "No cargar para instrumentación de aplicaciones backend con OpenTelemetry o métricas de negocio en Prometheus — para observabilidad de sistemas cargar `monitoring-alertas`."
|
|
16
|
+
- "No cargar para implementar sistemas de analytics propietarios o data warehouses (BigQuery, Snowflake) sin componente de tracking web — para pipelines de datos cargar el skill de cloud correspondiente."
|
|
17
|
+
- "No cargar para scraping o extracción de datos de plataformas publicitarias externas — para acceso a APIs de Google Ads o Meta Business cargar `paid-media-tracking`."
|
|
18
|
+
---
|
|
19
|
+
# tracking-measurement — Sistemas de medición web
|
|
20
|
+
|
|
21
|
+
## Cuándo NO cargar
|
|
22
|
+
|
|
23
|
+
- La tarea es analizar datos de conversiones ya capturados (ROAS, atribución): cargar `paid-media-tracking`.
|
|
24
|
+
- La tarea es instrumentación de backend con OpenTelemetry o Prometheus: cargar `monitoring-alertas`.
|
|
25
|
+
- La tarea es construir un data warehouse o pipeline de datos sin componente de tracking web: cargar el skill de cloud correspondiente.
|
|
26
|
+
- La tarea es acceder a APIs de Google Ads o Meta Business para reportes: cargar `paid-media-tracking`.
|
|
27
|
+
|
|
28
|
+
## Cuándo cargar este skill
|
|
29
|
+
|
|
30
|
+
- Configurar GTM: workspace, triggers, variables, tags
|
|
31
|
+
- Implementar eventos GA4 (e-commerce, custom dimensions, Measurement Protocol)
|
|
32
|
+
- Construir endpoint server-side para Meta Conversions API (CAPI)
|
|
33
|
+
- Implementar Enhanced Conversions de Google Ads
|
|
34
|
+
- Añadir Consent Mode v2 (GDPR/CCPA) a una aplicación web
|
|
35
|
+
- Integrar CMP (Cookiebot, OneTrust, Usercentrics) con GTM
|
|
36
|
+
- Depurar discrepancias entre datos de plataformas y datos reales
|
|
37
|
+
|
|
38
|
+
## Arquitectura de medición moderna
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
Navegador Servidor Plataformas
|
|
42
|
+
───────── ──────── ──────────
|
|
43
|
+
GTM Container Server-side GTM Google Analytics 4
|
|
44
|
+
└─ dataLayer.push() ──► (Cloud Run / App Engine) Meta Ads Manager
|
|
45
|
+
└─ GA4 tag ──► └─ GA4 Measurement API Google Ads
|
|
46
|
+
└─ Meta Pixel tag ──► └─ Meta CAPI Microsoft Ads
|
|
47
|
+
└─ Consent Mode ──► └─ Hash PII antes de enviar
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
El tracking browser-only pierde 40-60% de eventos en Safari/iOS por ITP.
|
|
51
|
+
El server-side tagging recupera esos eventos usando datos first-party.
|
|
52
|
+
|
|
53
|
+
## Reglas obligatorias
|
|
54
|
+
|
|
55
|
+
### Regla 1 — Limpiar ecommerce antes de cada evento
|
|
56
|
+
|
|
57
|
+
Siempre ejecutar `dataLayer.push({ ecommerce: null })` antes de cualquier
|
|
58
|
+
evento e-commerce. Sin esto, GTM mezcla datos de eventos anteriores.
|
|
59
|
+
|
|
60
|
+
**Verificación**: En Tag Assistant, cada evento e-commerce debe tener
|
|
61
|
+
`ecommerce: null` inmediatamente antes en el historial del dataLayer.
|
|
62
|
+
|
|
63
|
+
### Regla 2 — Hashear PII antes de enviar a plataformas externas
|
|
64
|
+
|
|
65
|
+
Email y teléfono NUNCA se envían en texto plano. Siempre SHA-256 normalizado:
|
|
66
|
+
email en minúsculas sin espacios, teléfono en formato E.164.
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
import hashlib
|
|
70
|
+
|
|
71
|
+
def hash_pii(valor: str) -> str:
|
|
72
|
+
"""Normaliza y hashea PII para plataformas externas (SHA-256)."""
|
|
73
|
+
return hashlib.sha256(valor.strip().lower().encode()).hexdigest()
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Verificación**: En los payloads de red (DevTools > Network), los campos
|
|
77
|
+
`em`, `ph`, `hashed_email` deben ser cadenas de 64 caracteres hexadecimales.
|
|
78
|
+
|
|
79
|
+
### Regla 3 — Deduplicación con event_id único
|
|
80
|
+
|
|
81
|
+
Cuando el mismo evento se envía desde browser (pixel) Y desde servidor (CAPI
|
|
82
|
+
o Measurement Protocol), AMBOS deben incluir el mismo `event_id`. Sin esto,
|
|
83
|
+
GA4 y Meta cuentan el evento dos veces.
|
|
84
|
+
|
|
85
|
+
```javascript
|
|
86
|
+
// Generar event_id antes de disparar el evento browser
|
|
87
|
+
const eventId = `purchase_${transactionId}_${Date.now()}`;
|
|
88
|
+
// Este mismo eventId se pasa al servidor para el envío CAPI
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Verificación**: En Meta Events Manager > Test Events, el campo "Match
|
|
92
|
+
type" debe mostrar "Deduplicated" para eventos con browser + server.
|
|
93
|
+
|
|
94
|
+
### Regla 4 — Consent Mode: default denied, actualizar al consentir
|
|
95
|
+
|
|
96
|
+
Inicializar Consent Mode con todo denegado ANTES de cargar GTM. Actualizar
|
|
97
|
+
solo después de que el usuario otorgue consentimiento explícito.
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
// Debe ejecutarse ANTES del snippet de GTM
|
|
101
|
+
window.dataLayer = window.dataLayer || [];
|
|
102
|
+
function gtag(){dataLayer.push(arguments);}
|
|
103
|
+
gtag('consent', 'default', {
|
|
104
|
+
analytics_storage: 'denied',
|
|
105
|
+
ad_storage: 'denied',
|
|
106
|
+
ad_user_data: 'denied',
|
|
107
|
+
ad_personalization: 'denied',
|
|
108
|
+
wait_for_update: 500,
|
|
109
|
+
});
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Verificación**: En Chrome DevTools > Application > Cookies, no deben
|
|
113
|
+
existir cookies `_ga`, `_fbp` antes de que el usuario acepte.
|
|
114
|
+
|
|
115
|
+
### Regla 5 — transaction_id único por compra
|
|
116
|
+
|
|
117
|
+
Un `transaction_id` duplicado en GA4 causa que la compra no se cuente
|
|
118
|
+
(deduplicación silenciosa). Usar el ID de orden del sistema, nunca
|
|
119
|
+
generado en frontend.
|
|
120
|
+
|
|
121
|
+
**Verificación**: En GA4 DebugView, el evento `purchase` debe aparecer
|
|
122
|
+
con el mismo `transaction_id` que la orden en la base de datos.
|
|
123
|
+
|
|
124
|
+
## dataLayer schema para e-commerce (GA4 Enhanced Ecommerce)
|
|
125
|
+
|
|
126
|
+
```javascript
|
|
127
|
+
window.dataLayer = window.dataLayer || [];
|
|
128
|
+
|
|
129
|
+
// Vista de producto
|
|
130
|
+
dataLayer.push({ ecommerce: null });
|
|
131
|
+
dataLayer.push({
|
|
132
|
+
event: 'view_item',
|
|
133
|
+
ecommerce: {
|
|
134
|
+
currency: 'MXN',
|
|
135
|
+
value: 299.00,
|
|
136
|
+
items: [{
|
|
137
|
+
item_id: 'SKU-001',
|
|
138
|
+
item_name: 'Producto Premium',
|
|
139
|
+
item_category: 'Software',
|
|
140
|
+
price: 299.00,
|
|
141
|
+
quantity: 1,
|
|
142
|
+
}]
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
// Compra completada
|
|
147
|
+
const eventId = `purchase_${transactionId}_${Date.now()}`;
|
|
148
|
+
dataLayer.push({ ecommerce: null });
|
|
149
|
+
dataLayer.push({
|
|
150
|
+
event: 'purchase',
|
|
151
|
+
event_id: eventId, // Para deduplicación con Meta CAPI
|
|
152
|
+
ecommerce: {
|
|
153
|
+
transaction_id: 'ORD-2026-001', // Único — del sistema backend
|
|
154
|
+
value: 299.00,
|
|
155
|
+
tax: 47.84,
|
|
156
|
+
currency: 'MXN',
|
|
157
|
+
items: [{
|
|
158
|
+
item_id: 'SKU-001',
|
|
159
|
+
item_name: 'Producto Premium',
|
|
160
|
+
price: 299.00,
|
|
161
|
+
quantity: 1,
|
|
162
|
+
}]
|
|
163
|
+
},
|
|
164
|
+
user_data: { // Para Enhanced Conversions (GTM hashea esto)
|
|
165
|
+
email_address: 'usuario@ejemplo.com',
|
|
166
|
+
phone_number: '+525512345678',
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## GA4 via Measurement Protocol (server-side)
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
import httpx
|
|
175
|
+
from app.core.config import settings
|
|
176
|
+
|
|
177
|
+
async def enviar_evento_ga4(
|
|
178
|
+
client_id: str,
|
|
179
|
+
evento: str,
|
|
180
|
+
parametros: dict,
|
|
181
|
+
session_id: str | None = None,
|
|
182
|
+
) -> None:
|
|
183
|
+
"""Envía evento a GA4 desde el servidor usando Measurement Protocol."""
|
|
184
|
+
payload = {
|
|
185
|
+
"client_id": client_id,
|
|
186
|
+
"events": [{
|
|
187
|
+
"name": evento,
|
|
188
|
+
"params": {
|
|
189
|
+
"session_id": session_id,
|
|
190
|
+
"engagement_time_msec": "100",
|
|
191
|
+
**parametros,
|
|
192
|
+
}
|
|
193
|
+
}]
|
|
194
|
+
}
|
|
195
|
+
async with httpx.AsyncClient() as client:
|
|
196
|
+
await client.post(
|
|
197
|
+
"https://www.google-analytics.com/mp/collect",
|
|
198
|
+
params={
|
|
199
|
+
"measurement_id": settings.GA4_MEASUREMENT_ID,
|
|
200
|
+
"api_secret": settings.GA4_API_SECRET, # Solo en servidor
|
|
201
|
+
},
|
|
202
|
+
json=payload,
|
|
203
|
+
timeout=5.0,
|
|
204
|
+
)
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
El `client_id` viene de la cookie `_ga`: formato `GA1.1.XXXXXXXXXX.XXXXXXXXXX`,
|
|
208
|
+
los dos últimos segmentos separados por punto.
|
|
209
|
+
|
|
210
|
+
## Anti-patrones críticos
|
|
211
|
+
|
|
212
|
+
| Anti-patrón | Problema | Solución |
|
|
213
|
+
|-------------|----------|----------|
|
|
214
|
+
| Email en texto plano en CAPI | Violación GDPR/Meta ToS | SHA-256 normalizado |
|
|
215
|
+
| `transaction_id` generado en frontend | Duplicados por recargas | Usar ID de orden del backend |
|
|
216
|
+
| Sin `ecommerce: null` previo | Datos de evento anterior contaminan | Siempre limpiar antes |
|
|
217
|
+
| `api_secret` de GA4 en frontend | Exposición de credenciales | Solo en variables de servidor |
|
|
218
|
+
| Pixel browser como única fuente | 40-60% pérdida en iOS | Agregar server-side CAPI |
|
|
219
|
+
| Consent Mode sin inicializar | Cookies antes del banner | Default denied antes de GTM |
|
|
220
|
+
|
|
221
|
+
## Referencias a recursos
|
|
222
|
+
|
|
223
|
+
| Tema | Archivo |
|
|
224
|
+
|------|---------|
|
|
225
|
+
| GTM: dataLayer avanzado, triggers, variables, workspace, server-side | [recursos/gtm-datalayer.md](recursos/gtm-datalayer.md) |
|
|
226
|
+
| Meta CAPI: endpoint completo, deduplicación, hashing PII, EMQ | [recursos/meta-capi.md](recursos/meta-capi.md) |
|
|
227
|
+
| Consent Mode v2, GDPR, CCPA, integración con CMPs | [recursos/consent-mode.md](recursos/consent-mode.md) |
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Gotchas / Errores comunes no obvios
|
|
232
|
+
|
|
233
|
+
**GTM dispara el tag de `purchase` dos veces en SPAs (React, Angular) porque el trigger "All Pages" se activa tanto en la carga inicial como en la navegación history-pushState, y el dataLayer push de compra queda en memoria entre rutas**: en una tienda Angular, el usuario completa la compra en `/checkout/success`, el evento `purchase` se envía correctamente. Pero si el usuario regresa a `/` usando el botón atrás y luego navega de nuevo a `/checkout/success` sin recargar, GTM vuelve a disparar el tag porque el dataLayer aún contiene el objeto `ecommerce` de la compra anterior. Causa: GTM persiste el dataLayer en memoria durante toda la sesión de la SPA; sin limpiar `{ ecommerce: null }` al navegar, el estado de eventos anteriores contamina rutas subsecuentes. Fix: en el router de la SPA, ejecutar `dataLayer.push({ ecommerce: null })` en cada cambio de ruta (Angular Router: `NavigationEnd` event), y usar triggers de GTM basados en evento personalizado (`purchase_completed`) en lugar de "All Pages" para eventos de conversión.
|
|
234
|
+
|
|
235
|
+
**Consent Mode v2 configurado con `wait_for_update: 500` bloquea el primer pageview de GA4 en dispositivos lentos donde el CMP tarda más de 500ms en renderizar, causando pérdida del 5-15% de pageviews en usuarios móviles con conexión 3G**: el banner de consentimiento en redes lentas tarda 800-1200ms en cargar el script del CMP. Durante ese tiempo, `wait_for_update: 500` expiró y GA4 disparó el pageview sin el estado de consentimiento correcto, lo que puede generar datos sin la cookie `_ga` y pageviews no atribuibles. Causa: `wait_for_update` es una espera máxima en milisegundos; si el CMP no llama a `gtag('consent', 'update', ...)` antes de ese límite, GA4 procede con el estado default. Fix: aumentar `wait_for_update` a 1500ms para móviles o implementar el CMP de forma que el script cargue de forma crítica (no diferida) para garantizar que actualiza el consentimiento antes del timeout.
|
|
236
|
+
|
|
237
|
+
**La deduplicación de Meta CAPI falla silenciosamente cuando el `event_id` del browser pixel y del server-side tienen formatos diferentes aunque semánticamente sean el mismo ID**: `event_id: "purchase_ORD-2026-001_1714500000000"` en el browser pixel y `event_id: "purchase_ord-2026-001_1714500000000"` (lowercase) en CAPI son tratados como eventos diferentes por Meta. Meta Events Manager muestra los dos como eventos separados sin deduplicar, duplicando las conversiones reportadas. Causa: Meta compara `event_id` como string exacto, case-sensitive. Fix: definir la generación del `event_id` en una sola función compartida (backend), enviarla al frontend como parte de la respuesta de creación de orden, y usar exactamente ese string en ambos lados. Documentar el formato como contrato: `purchase_{ORDER_ID_UPPERCASE}_{UNIX_TIMESTAMP_MS}`.
|
|
238
|
+
|
|
239
|
+
**El hashing SHA-256 de email para Meta CAPI falla en la deduplicación cuando el email viene con caracteres de espacio en blanco invisible (NBSP, U+00A0) que el usuario copió de un email de confirmación**: `hashlib.sha256("usuario@ejemplo.com".encode()).hexdigest()` y `hashlib.sha256("usuario@ejemplo.com\u00a0".encode()).hexdigest()` producen hashes completamente diferentes, y Meta no puede hacer match con el PII del usuario registrado. Causa: el método `.strip()` de Python elimina espacios ASCII (U+0020) pero no todos los caracteres de espacio Unicode como NBSP (U+00A0) o ZWSP (U+200B). Fix: normalizar el email con `unicodedata.normalize('NFKC', email).strip().lower()` antes del hash. La normalización NFKC convierte variantes Unicode de caracteres de espacio a sus equivalentes ASCII, garantizando consistencia del hash.
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
# Consent Mode v2: GDPR, CCPA e integración con CMPs
|
|
2
|
+
|
|
3
|
+
## Qué es Consent Mode v2
|
|
4
|
+
|
|
5
|
+
Consent Mode v2 es un mecanismo de Google que permite a los tags de Google
|
|
6
|
+
(GA4, Google Ads, Floodlight) adaptar su comportamiento según el consentimiento
|
|
7
|
+
del usuario. Introducido en 2024 como requisito para mantener la personalización
|
|
8
|
+
de anuncios en el EEE y UK.
|
|
9
|
+
|
|
10
|
+
### Los 4 parámetros de consentimiento
|
|
11
|
+
|
|
12
|
+
| Parámetro | Controla |
|
|
13
|
+
|-----------|----------|
|
|
14
|
+
| `analytics_storage` | Cookies de medición (GA4: `_ga`, `_ga_*`) |
|
|
15
|
+
| `ad_storage` | Cookies de publicidad (Google Ads, Floodlight) |
|
|
16
|
+
| `ad_user_data` | Envío de datos de usuario a Google para publicidad |
|
|
17
|
+
| `ad_personalization` | Remarketing y personalización de anuncios |
|
|
18
|
+
|
|
19
|
+
Cuando un parámetro está `denied`, Google no almacena cookies pero sí
|
|
20
|
+
registra eventos "sin cookies" (pings anónimos) para el modelado estadístico.
|
|
21
|
+
|
|
22
|
+
## Implementación base con gtag
|
|
23
|
+
|
|
24
|
+
El código de Consent Mode debe ejecutarse ANTES del snippet de GTM o gtag.
|
|
25
|
+
El orden importa: si GTM carga primero, puede crear cookies antes del consentimiento.
|
|
26
|
+
|
|
27
|
+
```html
|
|
28
|
+
<!-- 1. Snippet de Consent Mode — ANTES de GTM -->
|
|
29
|
+
<script>
|
|
30
|
+
window.dataLayer = window.dataLayer || [];
|
|
31
|
+
function gtag(){dataLayer.push(arguments);}
|
|
32
|
+
|
|
33
|
+
gtag('consent', 'default', {
|
|
34
|
+
analytics_storage: 'denied',
|
|
35
|
+
ad_storage: 'denied',
|
|
36
|
+
ad_user_data: 'denied',
|
|
37
|
+
ad_personalization: 'denied',
|
|
38
|
+
wait_for_update: 500, // ms para esperar la respuesta del CMP
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
gtag('set', 'ads_data_redaction', true); // Redactar URLs de click si denied
|
|
42
|
+
gtag('set', 'url_passthrough', true); // Pasar info de click en URL para atribución
|
|
43
|
+
</script>
|
|
44
|
+
|
|
45
|
+
<!-- 2. Snippet de GTM — DESPUÉS de Consent Mode -->
|
|
46
|
+
<script>
|
|
47
|
+
(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
|
48
|
+
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
|
|
49
|
+
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
|
50
|
+
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
|
51
|
+
})(window,document,'script','dataLayer','GTM-XXXXXXX');
|
|
52
|
+
</script>
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Actualizar consentimiento tras decisión del usuario
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
// Llamar después de que el usuario acepta en el banner del CMP
|
|
59
|
+
function otorgarConsentimiento(opciones) {
|
|
60
|
+
gtag('consent', 'update', {
|
|
61
|
+
analytics_storage: opciones.analytics ? 'granted' : 'denied',
|
|
62
|
+
ad_storage: opciones.publicidad ? 'granted' : 'denied',
|
|
63
|
+
ad_user_data: opciones.publicidad ? 'granted' : 'denied',
|
|
64
|
+
ad_personalization: opciones.publicidad ? 'granted' : 'denied',
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Llamar cuando el usuario rechaza todo
|
|
69
|
+
function rechazarConsentimiento() {
|
|
70
|
+
gtag('consent', 'update', {
|
|
71
|
+
analytics_storage: 'denied',
|
|
72
|
+
ad_storage: 'denied',
|
|
73
|
+
ad_user_data: 'denied',
|
|
74
|
+
ad_personalization: 'denied',
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Integración con CMPs
|
|
80
|
+
|
|
81
|
+
### Cookiebot
|
|
82
|
+
|
|
83
|
+
Cookiebot dispara el evento `CookiebotOnAccept` / `CookiebotOnDecline`.
|
|
84
|
+
Integración directa disponible en GTM como template oficial de la galería.
|
|
85
|
+
|
|
86
|
+
```javascript
|
|
87
|
+
// Listener para Cookiebot
|
|
88
|
+
window.addEventListener('CookiebotOnAccept', function() {
|
|
89
|
+
gtag('consent', 'update', {
|
|
90
|
+
analytics_storage: Cookiebot.consent.statistics ? 'granted' : 'denied',
|
|
91
|
+
ad_storage: Cookiebot.consent.marketing ? 'granted' : 'denied',
|
|
92
|
+
ad_user_data: Cookiebot.consent.marketing ? 'granted' : 'denied',
|
|
93
|
+
ad_personalization: Cookiebot.consent.marketing ? 'granted' : 'denied',
|
|
94
|
+
});
|
|
95
|
+
}, false);
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### OneTrust
|
|
99
|
+
|
|
100
|
+
OneTrust usa categorías de cookies mapeadas a grupos:
|
|
101
|
+
|
|
102
|
+
| Grupo OneTrust | Parámetro Consent Mode |
|
|
103
|
+
|---------------|----------------------|
|
|
104
|
+
| `C0002` (Performance) | `analytics_storage` |
|
|
105
|
+
| `C0004` (Targeting) | `ad_storage`, `ad_user_data`, `ad_personalization` |
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
// Template GTM disponible en: OneTrust > GTM Integration
|
|
109
|
+
// O implementación manual:
|
|
110
|
+
window.OneTrust?.OnConsentChanged(function(event) {
|
|
111
|
+
const activas = event.detail;
|
|
112
|
+
gtag('consent', 'update', {
|
|
113
|
+
analytics_storage: activas.includes('C0002') ? 'granted' : 'denied',
|
|
114
|
+
ad_storage: activas.includes('C0004') ? 'granted' : 'denied',
|
|
115
|
+
ad_user_data: activas.includes('C0004') ? 'granted' : 'denied',
|
|
116
|
+
ad_personalization: activas.includes('C0004') ? 'granted' : 'denied',
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Usercentrics
|
|
122
|
+
|
|
123
|
+
Usercentrics expone el objeto `UC_UI` y el evento `ucEvent`:
|
|
124
|
+
|
|
125
|
+
```javascript
|
|
126
|
+
window.addEventListener('ucEvent', function(e) {
|
|
127
|
+
if (e.detail?.event === 'consent_status') {
|
|
128
|
+
const servicios = e.detail;
|
|
129
|
+
gtag('consent', 'update', {
|
|
130
|
+
analytics_storage: servicios['Google Analytics'] ? 'granted' : 'denied',
|
|
131
|
+
ad_storage: servicios['Google Ads'] ? 'granted' : 'denied',
|
|
132
|
+
ad_user_data: servicios['Google Ads'] ? 'granted' : 'denied',
|
|
133
|
+
ad_personalization: servicios['Google Ads'] ? 'granted' : 'denied',
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Modelado de conversiones en GA4
|
|
140
|
+
|
|
141
|
+
Cuando `analytics_storage` o `ad_storage` está `denied`, GA4 no puede
|
|
142
|
+
atribuir conversiones directamente. Google utiliza ML para estimar las
|
|
143
|
+
conversiones faltantes basándose en usuarios con consentimiento similar.
|
|
144
|
+
|
|
145
|
+
**Condiciones para que el modelado funcione**:
|
|
146
|
+
- Mínimo 1,000 conversiones observables por semana.
|
|
147
|
+
- Tasa de consentimiento > 0% (si nadie acepta, no hay datos base).
|
|
148
|
+
- Consent Mode implementado correctamente (los pings anónimos llegan).
|
|
149
|
+
|
|
150
|
+
**Verificar que los pings llegan**: En GA4 > Admin > Data streams > tu stream >
|
|
151
|
+
Measurement Protocol. Debe mostrar eventos incluso de usuarios sin consentimiento
|
|
152
|
+
(aparecen como eventos anónimos sin `client_id`).
|
|
153
|
+
|
|
154
|
+
## GDPR: base legal por tipo de tracking
|
|
155
|
+
|
|
156
|
+
| Tipo de tracking | Base legal posible | Requiere banner |
|
|
157
|
+
|-----------------|-------------------|-----------------|
|
|
158
|
+
| Analytics de medición interna | Interés legítimo (debatible) | Sí, en la mayoría de países |
|
|
159
|
+
| Analytics para mejora de producto | Interés legítimo | Sí |
|
|
160
|
+
| Retargeting / remarketing | Consentimiento explícito | Sí, siempre |
|
|
161
|
+
| Conversiones para optimización de anuncios | Consentimiento explícito | Sí, siempre |
|
|
162
|
+
|
|
163
|
+
**Práctica recomendada**: usar consentimiento explícito para todo tracking
|
|
164
|
+
publicitario y analítico. El interés legítimo es cuestionable y está siendo
|
|
165
|
+
restringido en interpretaciones recientes del GDPR.
|
|
166
|
+
|
|
167
|
+
**Registro de consentimiento**: almacenar en base de datos:
|
|
168
|
+
- Fecha y hora de la decisión
|
|
169
|
+
- Versión de la política de privacidad aceptada
|
|
170
|
+
- Opciones específicas seleccionadas por el usuario
|
|
171
|
+
- IP anonimizada (últimos 2 octetos a 0)
|
|
172
|
+
|
|
173
|
+
## CCPA: opt-out en lugar de opt-in
|
|
174
|
+
|
|
175
|
+
En California (CCPA), el modelo es inverso al GDPR: tracking activo por
|
|
176
|
+
defecto, con obligación de ofrecer opt-out.
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
// URL de opt-out requerida por CCPA
|
|
180
|
+
// El usuario llega desde el enlace "No vender mi información personal"
|
|
181
|
+
if (new URLSearchParams(location.search).has('ccpa_opt_out')) {
|
|
182
|
+
gtag('consent', 'update', {
|
|
183
|
+
ad_storage: 'denied',
|
|
184
|
+
ad_user_data: 'denied',
|
|
185
|
+
ad_personalization: 'denied',
|
|
186
|
+
});
|
|
187
|
+
// Persistir la preferencia en localStorage
|
|
188
|
+
localStorage.setItem('ccpa_opt_out', 'true');
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// Al cargar la página, verificar opt-out previo
|
|
192
|
+
if (localStorage.getItem('ccpa_opt_out') === 'true') {
|
|
193
|
+
gtag('consent', 'update', {
|
|
194
|
+
ad_storage: 'denied',
|
|
195
|
+
ad_user_data: 'denied',
|
|
196
|
+
ad_personalization: 'denied',
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
**US Privacy String**: formato `1YNN` (versión 1, aviso notificado, opt-out no,
|
|
202
|
+
LSPA no). Incluir en requests de publicidad si se usa un ad server compatible.
|
|
203
|
+
|
|
204
|
+
## Verificación con Consent Mode Inspector
|
|
205
|
+
|
|
206
|
+
En Chrome DevTools > Application > Cookies:
|
|
207
|
+
- Antes de aceptar: no deben existir `_ga`, `_ga_*`, `_gcl_*`, `_fbp`
|
|
208
|
+
- Después de aceptar analytics: `_ga` y `_ga_MEASUREMENTID` deben aparecer
|
|
209
|
+
- Después de aceptar publicidad: `_gcl_au` (Google Ads) debe aparecer
|
|
210
|
+
|
|
211
|
+
En la consola del browser:
|
|
212
|
+
```javascript
|
|
213
|
+
// Ver estado actual del consentimiento
|
|
214
|
+
window.dataLayer.filter(e => e[0] === 'consent')
|
|
215
|
+
// Debe mostrar el 'default' y los 'update' aplicados
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
Con la extensión **Consent Mode Inspector** de Google (Chrome Web Store):
|
|
219
|
+
muestra en tiempo real el estado de cada parámetro y los cambios al interactuar
|
|
220
|
+
con el banner de consentimiento.
|
|
221
|
+
|
|
222
|
+
## Checklist de cumplimiento pre-lanzamiento
|
|
223
|
+
|
|
224
|
+
- [ ] Consent Mode inicializado ANTES del snippet de GTM
|
|
225
|
+
- [ ] Default: los 4 parámetros en `denied`
|
|
226
|
+
- [ ] Banner de CMP visible en primera visita para usuarios del EEE
|
|
227
|
+
- [ ] `gtag('consent', 'update', ...)` se ejecuta al aceptar/rechazar
|
|
228
|
+
- [ ] Sin cookies `_ga`, `_fbp` antes del consentimiento (verificar en DevTools)
|
|
229
|
+
- [ ] Registro de consentimiento almacenado en base de datos
|
|
230
|
+
- [ ] Enlace "No vender mi información" visible en footer (para CCPA)
|
|
231
|
+
- [ ] Política de privacidad actualizada con tecnologías de tracking usadas
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
# GTM: dataLayer avanzado, triggers, variables y server-side
|
|
2
|
+
|
|
3
|
+
## Arquitectura de GTM
|
|
4
|
+
|
|
5
|
+
GTM funciona con tres conceptos fundamentales que se relacionan en orden:
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
Trigger (cuándo) ──► Tag (qué hacer) ──► Variable (con qué datos)
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Un **trigger** detecta un evento en la página. Una **tag** se dispara cuando
|
|
12
|
+
el trigger se activa. Las **variables** proveen los datos que la tag necesita.
|
|
13
|
+
|
|
14
|
+
### Workspace y versiones
|
|
15
|
+
|
|
16
|
+
- El **workspace** es el entorno de trabajo en progreso (sin publicar).
|
|
17
|
+
- Cada **versión** es un snapshot publicado con nombre, fecha y descripción.
|
|
18
|
+
- Crear una versión antes de cada cambio relevante: `Versión > Nueva versión`.
|
|
19
|
+
- En producción usar siempre un contenedor publicado, nunca el workspace.
|
|
20
|
+
- Ambientes (`Environments`): crear uno por stage (dev, staging, prod) para
|
|
21
|
+
probar sin afectar el contenedor de producción.
|
|
22
|
+
|
|
23
|
+
## Variables
|
|
24
|
+
|
|
25
|
+
### Variables built-in
|
|
26
|
+
|
|
27
|
+
GTM incluye variables activables sin configuración extra:
|
|
28
|
+
|
|
29
|
+
| Variable | Valor |
|
|
30
|
+
|----------|-------|
|
|
31
|
+
| `Page URL` | URL completa de la página actual |
|
|
32
|
+
| `Page Path` | Solo el path: `/productos/sku-001` |
|
|
33
|
+
| `Click URL` | URL del elemento clickeado |
|
|
34
|
+
| `Click Text` | Texto del elemento clickeado |
|
|
35
|
+
| `Click Classes` | Clases CSS del elemento clickeado |
|
|
36
|
+
| `Form URL` | URL de acción del formulario enviado |
|
|
37
|
+
| `Scroll Depth Threshold` | Porcentaje de scroll alcanzado |
|
|
38
|
+
|
|
39
|
+
Activarlas en: Variables > Built-In Variables > Configure.
|
|
40
|
+
|
|
41
|
+
### Variables personalizadas de dataLayer
|
|
42
|
+
|
|
43
|
+
Para leer valores del objeto `ecommerce` del dataLayer:
|
|
44
|
+
|
|
45
|
+
- Tipo: **Data Layer Variable**
|
|
46
|
+
- Nombre de variable: `ecommerce.transaction_id` (notación de punto)
|
|
47
|
+
- Versión del dataLayer: **Version 2** (siempre para GA4)
|
|
48
|
+
- Nombre de la variable en GTM: `{{DL - ecommerce.transaction_id}}`
|
|
49
|
+
|
|
50
|
+
Convención de naming para variables de dataLayer: `{{DL - ruta.al.valor}}`.
|
|
51
|
+
|
|
52
|
+
### Variables de JavaScript personalizado
|
|
53
|
+
|
|
54
|
+
Para lógica más compleja (formateo, cálculos, lectura de cookies):
|
|
55
|
+
|
|
56
|
+
```javascript
|
|
57
|
+
// Variable: {{JS - GA Client ID}}
|
|
58
|
+
function() {
|
|
59
|
+
var cookie = document.cookie.match(/_ga=([^;]+)/);
|
|
60
|
+
if (!cookie) return undefined;
|
|
61
|
+
var parts = cookie[1].split('.');
|
|
62
|
+
return parts.slice(-2).join('.');
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
```javascript
|
|
67
|
+
// Variable: {{JS - FBC Cookie}}
|
|
68
|
+
function() {
|
|
69
|
+
var match = document.cookie.match(/_fbc=([^;]+)/);
|
|
70
|
+
return match ? match[1] : undefined;
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Triggers
|
|
75
|
+
|
|
76
|
+
### Tipos de trigger más usados
|
|
77
|
+
|
|
78
|
+
**All Pages (Pageview)**: Se dispara en cada carga de página. Base para GA4
|
|
79
|
+
Configuration tag. Siempre presente en todo contenedor.
|
|
80
|
+
|
|
81
|
+
**Custom Event**: Se dispara cuando `dataLayer.push({ event: 'nombre' })`
|
|
82
|
+
coincide con el nombre configurado. Usar para eventos de e-commerce.
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
Trigger > Custom Event
|
|
86
|
+
Event name: purchase
|
|
87
|
+
(Para capturar todos los eventos custom: usar regex .*)
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Click - All Elements**: Se dispara en cualquier click. Útil para tracking
|
|
91
|
+
de botones sin código JavaScript adicional.
|
|
92
|
+
|
|
93
|
+
**Form Submission**: Se dispara al enviar un formulario. Requiere activar
|
|
94
|
+
`Form` en Built-In Variables.
|
|
95
|
+
|
|
96
|
+
**History Change**: Esencial en Single-Page Apps (React, Angular, Vue) donde
|
|
97
|
+
la URL cambia sin recarga completa. Usar en lugar de Pageview para SPAs.
|
|
98
|
+
|
|
99
|
+
### Race conditions en SPAs
|
|
100
|
+
|
|
101
|
+
En aplicaciones de una sola página, el trigger `History Change` puede
|
|
102
|
+
dispararse antes de que el componente actualice el dataLayer. Solución:
|
|
103
|
+
|
|
104
|
+
```javascript
|
|
105
|
+
// Después del cambio de ruta, esperar al siguiente tick
|
|
106
|
+
router.afterEach((to) => {
|
|
107
|
+
setTimeout(() => {
|
|
108
|
+
dataLayer.push({ ecommerce: null });
|
|
109
|
+
dataLayer.push({
|
|
110
|
+
event: 'page_view',
|
|
111
|
+
page_path: to.path,
|
|
112
|
+
page_title: to.meta.title,
|
|
113
|
+
});
|
|
114
|
+
}, 0);
|
|
115
|
+
});
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Alternativa con GTM: usar la variable `{{JS - Page Path}}` con `Page Path`
|
|
119
|
+
built-in, que siempre refleja la URL actual al momento del trigger.
|
|
120
|
+
|
|
121
|
+
## Tags
|
|
122
|
+
|
|
123
|
+
### GA4 Configuration Tag
|
|
124
|
+
|
|
125
|
+
Una sola por contenedor. Se dispara en All Pages.
|
|
126
|
+
|
|
127
|
+
- Tag type: **Google Analytics: GA4 Configuration**
|
|
128
|
+
- Measurement ID: `{{Constant - GA4 Measurement ID}}`
|
|
129
|
+
- Fields to set: `debug_mode` = `true` (solo en workspace de desarrollo)
|
|
130
|
+
|
|
131
|
+
### GA4 Event Tag
|
|
132
|
+
|
|
133
|
+
Una por tipo de evento e-commerce.
|
|
134
|
+
|
|
135
|
+
- Tag type: **Google Analytics: GA4 Event**
|
|
136
|
+
- Configuration Tag: seleccionar la Configuration Tag creada arriba
|
|
137
|
+
- Event Name: `{{DL - event}}` (lee el nombre del evento del dataLayer)
|
|
138
|
+
- Trigger: Custom Event con el nombre del evento
|
|
139
|
+
|
|
140
|
+
Para pasar el objeto `ecommerce` completo:
|
|
141
|
+
- Event Parameters: agregar `items` = `{{DL - ecommerce.items}}`
|
|
142
|
+
- Marcar **Send Ecommerce data**: activado, Source: Data Layer
|
|
143
|
+
|
|
144
|
+
### Conversion Linker
|
|
145
|
+
|
|
146
|
+
Tag obligatoria para Enhanced Conversions y cross-device tracking:
|
|
147
|
+
|
|
148
|
+
- Tag type: **Conversion Linker**
|
|
149
|
+
- Trigger: All Pages
|
|
150
|
+
- Colocar antes que cualquier tag de conversión de Google Ads
|
|
151
|
+
|
|
152
|
+
## GTM Server-Side en Cloud Run
|
|
153
|
+
|
|
154
|
+
El servidor GTM actúa como proxy entre el browser y las plataformas de ads,
|
|
155
|
+
permitiendo enviar datos first-party sin depender de las restricciones del browser.
|
|
156
|
+
|
|
157
|
+
### Setup mínimo
|
|
158
|
+
|
|
159
|
+
1. Crear un contenedor de tipo **Server** en GTM.
|
|
160
|
+
2. Desplegar la imagen `gcr.io/cloud-tagging-10302018/gts-preview:latest`
|
|
161
|
+
en Cloud Run (mínimo 1 instancia siempre activa para latencia).
|
|
162
|
+
3. Configurar el **Server Container URL** en el contenedor browser de GTM.
|
|
163
|
+
4. Verificar que las requests van a `tu-dominio.com/g/collect` en vez de
|
|
164
|
+
directamente a `google-analytics.com`.
|
|
165
|
+
|
|
166
|
+
### Client templates
|
|
167
|
+
|
|
168
|
+
El servidor GTM necesita un **Client** que reciba las requests del browser:
|
|
169
|
+
|
|
170
|
+
- **GA4 Client**: recibe requests del tag GA4 del browser.
|
|
171
|
+
- **Meta Pixel Client**: recibe requests del Meta Pixel del browser.
|
|
172
|
+
|
|
173
|
+
Cada client parsea el payload y lo pone disponible para los tags del servidor.
|
|
174
|
+
|
|
175
|
+
### Tag templates del servidor
|
|
176
|
+
|
|
177
|
+
Los tags del servidor envían datos a las plataformas finales:
|
|
178
|
+
|
|
179
|
+
- **GA4 (server-side)**: usa `measurement_id` y `api_secret` como variables.
|
|
180
|
+
- **Meta CAPI**: usa `pixel_id` y `access_token` como variables de entorno.
|
|
181
|
+
|
|
182
|
+
Ventaja clave: las variables con credenciales viven en el servidor,
|
|
183
|
+
nunca expuestas en el browser.
|
|
184
|
+
|
|
185
|
+
## Modo de depuración
|
|
186
|
+
|
|
187
|
+
### Tag Assistant
|
|
188
|
+
|
|
189
|
+
1. En GTM workspace > Preview: abre Tag Assistant en una nueva pestaña.
|
|
190
|
+
2. Ingresar la URL del sitio y activar la sesión de debug.
|
|
191
|
+
3. El panel izquierdo muestra todos los eventos del dataLayer en orden.
|
|
192
|
+
4. Hacer click en un evento para ver qué tags se dispararon y cuáles no.
|
|
193
|
+
|
|
194
|
+
### GA4 DebugView
|
|
195
|
+
|
|
196
|
+
En GA4 > Admin > DebugView: muestra eventos en tiempo real del browser
|
|
197
|
+
con `debug_mode: true`. Indispensable para validar eventos e-commerce.
|
|
198
|
+
|
|
199
|
+
### Regla de validación antes de pasar a producción
|
|
200
|
+
|
|
201
|
+
1. Verificar en Tag Assistant que cada evento tiene `ecommerce: null` previo.
|
|
202
|
+
2. Confirmar en GA4 DebugView que el evento `purchase` llega con el
|
|
203
|
+
`transaction_id` correcto.
|
|
204
|
+
3. Publicar una versión con nombre descriptivo: `"feat: purchase event GA4"`.
|
|
205
|
+
4. Monitorear GA4 > Realtime durante las primeras 24 horas post-deploy.
|
|
206
|
+
|
|
207
|
+
## Buenas prácticas de naming
|
|
208
|
+
|
|
209
|
+
| Tipo | Convención | Ejemplo |
|
|
210
|
+
|------|-----------|---------|
|
|
211
|
+
| Variable dataLayer | `{{DL - ruta.del.valor}}` | `{{DL - ecommerce.transaction_id}}` |
|
|
212
|
+
| Variable JavaScript | `{{JS - Descripción}}` | `{{JS - GA Client ID}}` |
|
|
213
|
+
| Constante | `{{Constant - Nombre}}` | `{{Constant - GA4 Measurement ID}}` |
|
|
214
|
+
| Trigger custom event | Igual que el nombre del evento | `purchase`, `view_item` |
|
|
215
|
+
| Tag GA4 | `GA4 - Nombre del evento` | `GA4 - Purchase`, `GA4 - Config` |
|
|
216
|
+
| Tag conversión | `Ads - Nombre conversión` | `Ads - Purchase Conversion` |
|