Architecture overview for Forge Apps

Architecture overview and best practices for privacy-aware analytics

📦

Working Example Available

The following code is available in our sample app available on GitHub.

🔗 View the full Forge Analytics Example on GitHub

The Problem: Traditional analytics are privacy nightmares

Most analytics implementations are extremely leaky when it comes to personally identifiable information (PII) and End User Data (EUD). Frontend analytics automatically transmit:

  • User IP addresses (tracks location, identifies companies)
  • Browser referrer URLs (reveals internal Jira/Confluence navigation)
  • Full page URLs (contains project names, issue keys, sensitive data)
  • Page titles (contains issue summaries and keys)
  • User agent strings (device fingerprinting)
  • Session cookies (cross-site tracking)
  • Form data (accidentally capturing sensitive information and end user data)
// ❌ DANGEROUS: Typical frontend analytics
gtag('event', 'search', {
  search_term: 'ACME Corp Salary Review'  // Customer data leak!
});
// Google now knows about ACME Corp's HR processes

The Solution: Complete Backend Control

By routing ALL analytics through your backend, you control exactly what information reaches your analytics provider. No accidents, no leaks, less chance of compliance violations.

Frontend Events → Backend Resolver → Queue → Consumer → Analytics Provider
                                   ↑
                      Backend Events

Architecture Overview

This implementation uses a queue-based, privacy-first architecture with six core components that work together to provide enterprise-ready analytics while maintaining Atlassian compliance.

Frontend Layer

Frontend Events Module (static/spa/src/analytics/events.js)

  • Purpose: Central registry for all UI interaction tracking
  • Key Functions: trackTodoItemsLoaded(), optional identify() and group()
  • Privacy Protection: Only sends event names via invoke() - no PII, no URLs, no browser data
  • Integration: React components import specific tracking functions for consistency

Backend Layer

Backend Events Module (src/analytics/events.js)

  • Purpose: Central definition of business events and main tracking logic
  • Key Functions: trackCreate(), trackUpdate(), trackDelete(), trackDeleteAll(), core track() function
  • Architecture Role: Processes both frontend-routed events and direct backend events through unified queue system

Resolver Bridge (src/analytics/resolvers.js)

  • Purpose: Privacy barrier between frontend and analytics provider
  • Key Functions: trackEvent() (main frontend bridge), optional identify() and group()
  • Privacy Filter: Receives minimal frontend data, adds backend context, forwards to queue

Queue Infrastructure

Queue Consumer (src/analytics/consumer.js)

  • Purpose: Asynchronous event processing with automatic retry
  • Architecture: Processes three event types: identify, group, track
  • Reliability: Handles provider outages without affecting user experience
  • Configuration: Defined in manifest.yml as analytics-consumer with analytics-queue

HTTP Dispatcher (src/analytics/dispatcher.js)

  • Purpose: Transport layer to analytics provider (Accoil)
  • Key Functions: handleTrackEvent(), handleIdentify(), handleGroup()
  • Provider Support: Built with common format that works across analytics providers
  • Debug Mode: Environment-controlled logging for development testing

Supporting Components

Utility Functions (src/analytics/utils.js)

  • Purpose: Consistent identity management and data extraction
  • Key Functions: userIdFromContext(), groupIdFromContext()
  • Cost Optimization: Configurable user identification strategy (individual vs instance-level)

Scheduled Analytics (src/analytics/schedule.js)

  • Purpose: Automated organizational data updates
  • Function: dailyGroupAnalytics() - updates license status, usage metrics
  • Trigger: Daily scheduled job configured in manifest.yml
  • Data: Instance-level traits, license information, activity metrics

Infrastructure Configuration

Manifest Declaration (manifest.yml)

  • Queue System: Consumer, queue, and function definitions
  • Scheduled Triggers: Daily analytics jobs
  • External Permissions: Backend-only analytics egress with inScopeEUD: false
  • Critical Setting: category: analytics and inScopeEUD: false protect "Runs on Atlassian" status

Data Flow Architecture

Frontend-Triggered Events

  1. User Interaction → Component calls trackTodoItemsLoaded()
  2. Frontend Bridgeinvoke('track-event', {event: 'Todos Loaded'})
  3. Resolver Processing → Backend receives event name + Forge context
  4. Queue Insertion → Event bundled with identity/group data and queued
  5. Async Processing → Consumer processes event when provider is available
  6. HTTP Delivery → Dispatcher sends to analytics provider

Backend-Triggered Events

  1. Business Logic → Todo created in resolver.define('create')
  2. Direct Trackingawait trackCreate(context) called immediately
  3. Queue Processing → Same queue/consumer/dispatcher flow as frontend events

Scheduled Events

  1. Daily Trigger → Forge executes dailyGroupAnalytics()
  2. Data Collection → Gathers license info, usage metrics, instance status
  3. Direct Dispatch → Bypasses queue (already scheduled), sends directly to provider

Privacy Protection Guarantees

Risk CategoryFrontend AnalyticsThis Architecture
IP Addresses❌ User's real IP sent✅ Only Forge server IP visible
URLs/Referrers❌ Internal URLs leaked✅ Never transmitted to provider
Browser Data❌ Full user agent sent✅ Server-controlled data only
Session Data❌ Cookies, localStorage exposed✅ No client-side data access
Form Inputs❌ Accidentally captured PII✅ Only intentional business events
Navigation Patterns❌ Full browsing history✅ Meaningful business actions only

Key Architecture Principles

  1. Privacy by Design: No accidental PII transmission possible
  2. Provider Abstraction: Easy switching between analytics services
  3. Central Event Management: Single source of truth for all tracked events
  4. Queue-Based Reliability: Enterprise-grade event delivery
  5. Customer Control: Customers can disable analytics via Atlassian controls.
  6. Compliance First: Built to exceed Atlassian's privacy requirements

Bottom Line: This architecture doesn't just ensure compliance—it provides competitive advantage through customer trust and enterprise readiness.


What’s Next