Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions deploy.json
Original file line number Diff line number Diff line change
Expand Up @@ -457,5 +457,14 @@
"veo/**",
"shared/**"
]
},
"google-analytics": {
"site": "google-analytics",
"entrypoint": "./dist/server/main.js",
"platformName": "kubernetes-bun",
"watch": [
"google-analytics/**",
"shared/**"
]
}
}
33 changes: 33 additions & 0 deletions google-analytics/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Dependencies
node_modules/

# Build output
dist/

# Environment
.env
.env.local

# OS files
.DS_Store
Thumbs.db

# IDE
.vscode/
.idea/

# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Data
data/
*.db
*.sqlite

# Template files
# Note: Keep app.json.example, ignore app.json if it's just a copy
# app.json

13 changes: 13 additions & 0 deletions google-analytics/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# google-analytics

Official Google Analytics (GA4) MCP integration

## Getting Started

1. Configure your MCP in `server/types/env.ts`
2. Implement tools in `server/tools/`
3. Rename `app.json.example` to `app.json` and customize
4. Add to `deploy.json` for deployment
5. Test with `bun run dev`

See [template-minimal/README.md](../template-minimal/README.md) for detailed instructions.
32 changes: 32 additions & 0 deletions google-analytics/app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"scopeName": "deco",
"name": "google-analytics",
"friendlyName": "Google Analytics",
"connection": {
"type": "HTTP",
"url": "https://sites-google-analytics.deco.site/mcp"
},
"description": "Integrate with Google Analytics 4 (GA4) to query reports, fetch realtime data, and manage analytics properties.",
"icon": "https://www.gstatic.com/analytics-suite/header/suite/v2/ic_analytics.svg",
"unlisted": false,
"auth": {
"type": "oauth2"
},
"metadata": {
"categories": [
"Analytics",
"Marketing",
"Data"
],
"official": false,
"tags": [
"google",
"analytics",
"ga4",
"data",
"reporting"
],
"short_description": "Integrate with Google Analytics 4 (GA4) to query reports, fetch realtime data, and manage analytics properties.",
"mesh_description": "The Google Analytics 4 (GA4) MCP provides comprehensive programmatic access to your Analytics data. **Key Features** - Query custom reports with dimensions and metrics using the Data API. Fetch realtime active users data. Retrieve metadata for custom dimensions and metrics. Navigate your account hierarchy. **Use Cases** - Perfect for marketers and developers needing to automate analytics reporting, identify top-performing content, or monitor active audiences directly from the LLM. **Authentication** - Uses OAuth 2.0 with Google Analytics read-only scope for secure access."
}
}
25 changes: 25 additions & 0 deletions google-analytics/app.json.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"scopeName": "deco",
"name": "my-mcp",
"friendlyName": "My MCP",
"connection": {
"type": "HTTP",
"url": "https://sites-my-mcp.decocache.com/mcp"
},
"description": "Short description of what this MCP does (1-2 sentences)",
"icon": "https://assets.decocache.com/mcp/{uuid}/icon.png",
"unlisted": false,
"auth": {
"type": "token",
"header": "Authorization",
"prefix": "Bearer"
},
"metadata": {
"categories": ["Productivity"],
"official": false,
"tags": ["example", "template", "mcp"],
"short_description": "Short description of what this MCP does",
"mesh_description": "Detailed description of your MCP (max 1500 characters). Explain what it does, key features, use cases, and authentication method. Use **bold** for feature names. Example: **Key Features** - Feature 1 description. **Use Cases** - Use case description. **Authentication** - How to authenticate. Perfect for developers who need [your use case]. Provides [your benefit]."
}
}

27 changes: 27 additions & 0 deletions google-analytics/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "google-analytics",
"version": "1.0.0",
"description": "Official Google Analytics (GA4) MCP integration",
"private": true,
"type": "module",
"scripts": {
"dev": "bun run --hot server/main.ts",
"check": "tsc --noEmit",
"build:server": "NODE_ENV=production bun build server/main.ts --target=bun --outfile=dist/server/main.js",
"build": "bun run build:server"
},
"dependencies": {
"@decocms/runtime": "1.3.1",
"zod": "^4.0.0"
},
"devDependencies": {
"@decocms/mcps-shared": "workspace:*",
"@modelcontextprotocol/sdk": "1.25.1",
"bun-types": "^1.3.7",
"deco-cli": "^0.28.0",
"typescript": "^5.7.2"
},
"engines": {
"node": ">=22.0.0"
}
}
36 changes: 36 additions & 0 deletions google-analytics/server/instructions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
export const instructions = `You are a Google Analytics 4 (GA4) specialized assistant.
Your goal is to help the user query their Google Analytics 4 data effectively.

## Property identification

If the user does not provide a GA4 property ID:
1. Call \`get-account-summaries\` to discover all accessible accounts and properties.
2. If multiple properties exist, list them and ask the user which one to query.
3. Property IDs can be provided as "properties/1234567" or just the numeric part "1234567" — both are accepted.

## Available tools

- \`get-account-summaries\` — Lists all GA4 accounts and properties the user can access.
- \`get-property-details\` — Returns configuration details for a property.
- \`get-custom-dimensions-and-metrics\` — Retrieves custom dimensions/metrics configured for a property. Call this before crafting reports that reference custom fields.
- \`run-report\` — Runs a standard GA4 Data API report with date ranges, dimensions, metrics, filters, and ordering.
- \`run-funnel-report\` — Analyzes how users progress through a sequence of steps (e.g. landing page → product → checkout → purchase). Each step is a FunnelStep with a name and filterExpression.
- \`run-realtime-report\` — Returns live data from the last 30 minutes (no date ranges required).
- \`list-google-ads-links\` — Lists Google Ads accounts linked to a GA4 property.
- \`list-property-annotations\` — Returns timestamped annotations on a property (campaign launches, code deploys, tracking changes). Useful for explaining traffic anomalies.

## Reporting tips

- \`dateRanges\` format: \`{ startDate: "30daysAgo", endDate: "today" }\` — also accepts YYYY-MM-DD dates.
- Standard dimension names: \`sessionSource\`, \`sessionMedium\`, \`pagePath\`, \`deviceCategory\`, \`country\`.
- Standard metric names: \`activeUsers\`, \`sessions\`, \`screenPageViews\`, \`bounceRate\`, \`averageSessionDuration\`.
- Use \`dimensionFilter\` / \`metricFilter\` for scoped queries (e.g. filter to a specific page or source).
- Use \`limit\` + \`offset\` to paginate through large result sets.
- Use \`returnPropertyQuota: true\` to check remaining API quota in the response.

## Funnel report tips

- \`funnelSteps\` requires at least 2 steps. Each step needs \`name\` and a \`filterExpression\` matching the event or page that defines the step.
- Example step: \`{ "name": "Purchase", "filterExpression": { "funnelEventFilter": { "eventName": "purchase" } } }\`
- Use \`funnelBreakdown\` to split funnel rows by a dimension (e.g. \`deviceCategory\`, \`sessionSource\`).
- Use \`funnelNextAction\` to see what users do after abandoning each step.`;
18 changes: 18 additions & 0 deletions google-analytics/server/lib/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { Env } from "../types/env.ts";

/**
* Get Google OAuth access token from environment context
* @param env - The environment containing the mesh request context
* @returns The OAuth access token
* @throws Error if not authenticated
*/
export const getGoogleAccessToken = (env: Env): string => {
const authorization = env.MESH_REQUEST_CONTEXT?.authorization;
const token = authorization?.replace(/^Bearer\s+/i, "").trim();
if (!token) {
throw new Error(
"Not authenticated. Please authorize with Google Analytics first.",
);
}
return token;
};
Loading
Loading