A visual node-based diagramming tool for planning Google Tag Manager implementations. Drag-and-drop GTM components onto a canvas, connect them to map data flow, and save architectures to your Google Drive.
- Google OAuth sign-in — each user authenticates with their Google account
- Google Drive persistence — projects auto-save to your personal
gtm-workflow-backupsDrive folder (one JSON per project) - Drag-and-drop nodes from the sidebar onto the canvas
- Connect components by dragging between handles to visualize data flow
- Pre-built templates for common GTM architectures (GA4, Server-Side CAPI, E-commerce, Hybrid)
- Domain scanner — automatically detect tags on any website (including GTM-injected tags) and import them to canvas
- JSON export/import to share architectures with your team
- PNG export of canvas diagrams
| Category | Components |
|---|---|
| Infrastructure | Website / Data Layer, GTM Client Container, GTM Server Container, Data Stream |
| Tags | GA4, Meta Pixel, Google Ads, TikTok, LinkedIn, Pinterest, Snapchat, X (Twitter), Custom HTML, Floodlight, Hotjar, Microsoft Clarity, CMP |
| Logic | Triggers, Variables |
| Annotations | Zone (resizable colored group boxes) |
- Basic GA4 Setup — Website → GTM Client → GA4
- Server-Side with Facebook CAPI — Website → GTM Client → GTM Server → GA4 + Meta CAPI + Google Ads
- Multi-Platform E-commerce — GA4 + Meta + TikTok + LinkedIn via client-side GTM
- Hybrid Client + Server — Client-side analytics + server-side conversion tracking
| Dependency | Version | Purpose |
|---|---|---|
| Node.js | 18+ | Frontend + auth/API server |
| npm | 9+ | Package management |
| Python | 3.9+ | Backend for domain scanner (optional) |
- Go to Google Cloud Console
- Create an OAuth 2.0 Client ID (Web application)
- Add authorized JavaScript origin:
http://localhost:5173 - Enable the Google Drive API for the project
- Copy your Client ID into
.env.local:
VITE_GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.comNote: Authentication uses client-side Google Identity Services (GIS). The browser gets an access token directly from Google — no server-side secret or redirect URI needed for development or static deployments.
npm install
# Vite frontend (the only server you need)
npm run devThe app will be available at http://localhost:5173. Sign in with Google to start creating and saving projects.
For Docker / Cloudron / Easypanel deployments, the server-side auth proxy handles OAuth via redirect:
AUTH_SECRET=random-hex-string-at-least-32-bytes
AUTH_GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
AUTH_GOOGLE_CLIENT_SECRET=GOCSPX-your-secret
AUTH_REDIRECT_URI=https://your-app.example.com/api/auth/google/callbackGenerate a secure AUTH_SECRET:
node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"npm run build
node --env-file=.env server.jsThe domain scanner uses a local Flask + Playwright backend to detect tags on websites:
cd backend
pip3 install -r requirements.txt
python3 -m playwright install chromium
python3 app.pyNote: The domain scanner backend is local-only and not deployed to production.
npm run build # TypeScript check + Vite build → dist/
npm run preview # Preview production buildThe output dist/ folder is fully static — deploy it anywhere.
All platforms require one build-time env var:
| Variable | Value |
|---|---|
VITE_GOOGLE_CLIENT_ID |
Your Google OAuth Client ID (e.g. 123456-abc.apps.googleusercontent.com) |
After deploying, add your production domain to your OAuth client:
- Go to Google Cloud Console → Credentials
- Edit your OAuth 2.0 Client → Authorized JavaScript origins
- Add your deployed URL (e.g.
https://gtm-workflow.netlify.app)
| Platform | Build command | Publish directory |
|---|---|---|
| Netlify | npm run build |
dist |
| Vercel | npm run build |
dist |
| GitHub Pages | npm run build |
dist (use base: '/gtm-workflow/' in vite.config.ts) |
- React 19 + TypeScript 5.9
- React Flow (
@xyflow/react) — node-based diagram engine - Zustand — state management
- Tailwind CSS 4 — styling
- Lucide React — icons
- Vite 7 — build tool & dev server
- Google Identity Services — client-side OAuth
- Google Drive REST API — project persistence
├── index.html Entry point (loads GIS script)
├── vite.config.ts Build config
├── .env.local VITE_GOOGLE_CLIENT_ID (not committed)
│
├── src/
│ ├── App.tsx Auth gate → loads last project
│ ├── components/ Canvas, Sidebar, Toolbar, ProjectManager, LoginPage
│ ├── nodes/ BaseNode + custom node types (Website, GTM, Tags, etc.)
│ ├── edges/ Animated DataFlowEdge with delete button
│ ├── store/ Zustand (useFlowStore, useAuthStore)
│ ├── data/ Tag registry (icons, colors) + templates
│ └── utils/
│ ├── googleAuth.ts GIS token client (sign-in, refresh, sign-out)
│ ├── driveApi.ts Direct Drive API (list, upload, delete)
│ ├── storage.ts Project persistence layer (uses driveApi)
│ └── exportPng.ts Canvas-to-PNG export
│
├── server.js Self-hosted production server (auth + Drive proxy)
├── auth.js Server-side OAuth (for Docker/Cloudron/Easypanel)
├── gdrive.js Server-side Drive ops (per-user tokens from session)
├── backend/ Flask domain scanner (optional, local-only)
└── plugins/ Vite dev middleware (offline/local mode)
- User signs in via Google popup (GIS token model) — no server redirect needed
- Access token stored in
sessionStorage(cleared on tab close) - Projects saved as individual JSON files in user's
gtm-workflow-backupsDrive folder - Folder is auto-created on first save
- Token auto-refreshes silently; re-prompts user if consent expired
MIT