bmad-plus 0.4.0 → 0.4.2

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.
Files changed (68) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +13 -56
  3. package/osint-agent-package/skills/bmad-osint-investigate/osint/SKILL.md +452 -452
  4. package/osint-agent-package/skills/bmad-osint-investigate/osint/assets/dossier-template.md +116 -116
  5. package/osint-agent-package/skills/bmad-osint-investigate/osint/references/content-extraction.md +100 -100
  6. package/osint-agent-package/skills/bmad-osint-investigate/osint/references/platforms.md +130 -130
  7. package/osint-agent-package/skills/bmad-osint-investigate/osint/references/psychoprofile.md +69 -69
  8. package/osint-agent-package/skills/bmad-osint-investigate/osint/references/tools.md +281 -281
  9. package/osint-agent-package/skills/bmad-osint-investigate/osint/scripts/mcp-client.py +136 -136
  10. package/package.json +1 -1
  11. package/readme-international/README.de.md +1 -1
  12. package/readme-international/README.es.md +1 -1
  13. package/readme-international/README.fr.md +1 -1
  14. package/tools/cli/commands/install.js +88 -59
  15. package/tools/cli/i18n.js +501 -0
  16. package/oveanet-pack/animated-website/DEPLOYMENT.md +0 -104
  17. package/oveanet-pack/animated-website/README.md +0 -63
  18. package/oveanet-pack/animated-website/agent.yaml +0 -63
  19. package/oveanet-pack/seo-audit-360/DEPLOYMENT.md +0 -115
  20. package/oveanet-pack/seo-audit-360/README.md +0 -66
  21. package/oveanet-pack/seo-audit-360/agent.yaml +0 -70
  22. package/oveanet-pack/seo-audit-360/extensions/google-analytics/EXTENSION.md +0 -79
  23. package/oveanet-pack/seo-audit-360/extensions/google-analytics/ga4_client.py +0 -200
  24. package/oveanet-pack/seo-audit-360/extensions/google-analytics/requirements.txt +0 -4
  25. package/oveanet-pack/seo-audit-360/extensions/google-search-console/EXTENSION.md +0 -109
  26. package/oveanet-pack/seo-audit-360/extensions/google-search-console/gsc_client.py +0 -186
  27. package/oveanet-pack/seo-audit-360/extensions/google-search-console/requirements.txt +0 -4
  28. package/oveanet-pack/seo-audit-360/hooks/seo-check.sh +0 -95
  29. package/oveanet-pack/seo-audit-360/requirements.txt +0 -14
  30. package/oveanet-pack/seo-audit-360/scripts/__pycache__/seo_crawl.cpython-314.pyc +0 -0
  31. package/oveanet-pack/seo-audit-360/scripts/__pycache__/seo_parse.cpython-314.pyc +0 -0
  32. package/oveanet-pack/seo-audit-360/scripts/install.ps1 +0 -53
  33. package/oveanet-pack/seo-audit-360/scripts/install.sh +0 -48
  34. package/oveanet-pack/seo-audit-360/scripts/seo_apis.py +0 -464
  35. package/oveanet-pack/seo-audit-360/scripts/seo_crawl.py +0 -282
  36. package/oveanet-pack/seo-audit-360/scripts/seo_fetch.py +0 -231
  37. package/oveanet-pack/seo-audit-360/scripts/seo_parse.py +0 -255
  38. package/oveanet-pack/seo-audit-360/scripts/seo_report.py +0 -403
  39. package/oveanet-pack/seo-audit-360/scripts/seo_screenshot.py +0 -202
  40. package/oveanet-pack/seo-audit-360/tests/__pycache__/test_crawl.cpython-314-pytest-9.0.2.pyc +0 -0
  41. package/oveanet-pack/seo-audit-360/tests/__pycache__/test_parse.cpython-314-pytest-9.0.2.pyc +0 -0
  42. package/oveanet-pack/seo-audit-360/tests/fixtures/sample_page.html +0 -62
  43. package/oveanet-pack/seo-audit-360/tests/test_apis.py +0 -75
  44. package/oveanet-pack/seo-audit-360/tests/test_crawl.py +0 -121
  45. package/oveanet-pack/seo-audit-360/tests/test_fetch.py +0 -70
  46. package/oveanet-pack/seo-audit-360/tests/test_parse.py +0 -184
  47. package/oveanet-pack/universal-backup/DEPLOYMENT.md +0 -80
  48. package/oveanet-pack/universal-backup/README.md +0 -58
  49. package/oveanet-pack/universal-backup/agent.yaml +0 -45
  50. /package/{oveanet-pack/animated-website/agent → src/bmad-plus/agents/pack-animated}/animated-website-agent.md +0 -0
  51. /package/{oveanet-pack/animated-website → src/bmad-plus/agents/pack-animated}/templates/animated-website-workflow.md +0 -0
  52. /package/{oveanet-pack/universal-backup/agent → src/bmad-plus/agents/pack-backup}/backup-agent.md +0 -0
  53. /package/{oveanet-pack/universal-backup → src/bmad-plus/agents/pack-backup}/templates/backup-workflow.md +0 -0
  54. /package/{oveanet-pack/seo-audit-360 → src/bmad-plus/agents/pack-seo}/SKILL.md +0 -0
  55. /package/{oveanet-pack/seo-audit-360 → src/bmad-plus/agents/pack-seo}/checklist.md +0 -0
  56. /package/{oveanet-pack/seo-audit-360 → src/bmad-plus/agents/pack-seo}/pagespeed-playbook.md +0 -0
  57. /package/{oveanet-pack/seo-audit-360 → src/bmad-plus/agents/pack-seo}/ref/audit-schema.json +0 -0
  58. /package/{oveanet-pack/seo-audit-360 → src/bmad-plus/agents/pack-seo}/ref/cwv-thresholds.md +0 -0
  59. /package/{oveanet-pack/seo-audit-360 → src/bmad-plus/agents/pack-seo}/ref/eeat-criteria.md +0 -0
  60. /package/{oveanet-pack/seo-audit-360 → src/bmad-plus/agents/pack-seo}/ref/geo-signals.md +0 -0
  61. /package/{oveanet-pack/seo-audit-360 → src/bmad-plus/agents/pack-seo}/ref/hreflang-rules.md +0 -0
  62. /package/{oveanet-pack/seo-audit-360 → src/bmad-plus/agents/pack-seo}/ref/quality-gates.md +0 -0
  63. /package/{oveanet-pack/seo-audit-360 → src/bmad-plus/agents/pack-seo}/ref/schema-catalog.md +0 -0
  64. /package/{oveanet-pack/seo-audit-360 → src/bmad-plus/agents/pack-seo}/ref/schema-templates.json +0 -0
  65. /package/{oveanet-pack/seo-audit-360/agent → src/bmad-plus/agents/pack-seo}/seo-chief.md +0 -0
  66. /package/{oveanet-pack/seo-audit-360/agent → src/bmad-plus/agents/pack-seo}/seo-judge.md +0 -0
  67. /package/{oveanet-pack/seo-audit-360/agent → src/bmad-plus/agents/pack-seo}/seo-scout.md +0 -0
  68. /package/{oveanet-pack/seo-audit-360 → src/bmad-plus/agents/pack-seo}/templates/seo-audit-workflow.md +0 -0
@@ -1,63 +0,0 @@
1
- name: animated-website
2
- version: 1.0.0
3
- title: "Animated Website"
4
- description: "Convertit des vidéos MP4 en sites web animés de luxe avec scroll frame-by-frame"
5
- author: Laurent ROCHETTA AI
6
- icon: "🎬"
7
- tags: [animation, scroll, video, luxury, canvas, webp]
8
- triggers:
9
- - "animated website"
10
- - "scroll animation"
11
- - "video to website"
12
- - "Apple-style page"
13
- - "scroll-driven site"
14
- - "frame animation"
15
- - "site animé"
16
- requires:
17
- tools:
18
- - name: ffmpeg
19
- install:
20
- windows: "winget install FFmpeg"
21
- mac: "brew install ffmpeg"
22
- linux: "sudo apt install ffmpeg"
23
- - name: python3
24
- install:
25
- windows: "winget install Python.Python.3"
26
- mac: "brew install python3"
27
- linux: "sudo apt install python3"
28
- scripts:
29
- - "scripts/extract_frames.py"
30
- commands: []
31
- workflow:
32
- - step: 1
33
- name: "Analyze Video"
34
- tool: "ffprobe"
35
- - step: 2
36
- name: "Extract Frames"
37
- tool: "extract_frames.py"
38
- - step: 3
39
- name: "Prepare Content"
40
- tool: "agent"
41
- - step: 4
42
- name: "Generate HTML"
43
- tool: "agent"
44
- - step: 5
45
- name: "Preview"
46
- tool: "python http.server"
47
- platforms:
48
- bmad:
49
- target: "_bmad/core/agents/"
50
- file: "animated-website-agent.md"
51
- claude:
52
- target: ".claude/skills/"
53
- skillName: "animated-website"
54
- includeScripts: true
55
- gemini:
56
- target: ".agent/workflows/"
57
- file: "animated-website.md"
58
- opencode:
59
- target: ".opencode/agents/"
60
- file: "animated-website.md"
61
- codex:
62
- target: ".codex/agents/"
63
- file: "animated-website.md"
@@ -1,115 +0,0 @@
1
- # Guide de Déploiement — Agent Audit SEO/GEO 360°
2
-
3
- ## Comment déployer cet agent dans un nouveau projet
4
-
5
- ### Prérequis
6
-
7
- Votre projet doit utiliser le framework BMAD (dossier `_bmad/` à la racine).
8
-
9
- ---
10
-
11
- ## Méthode 1 : Déploiement BMAD (recommandé)
12
-
13
- ### Étape 1 — Copier l'agent
14
-
15
- ```
16
- Copiez le fichier :
17
- Audit SEO GEO 360/agent/seo-geo-360-auditor.md
18
-
19
- Dans le dossier de votre projet :
20
- {votre-projet}/_bmad/core/agents/seo-geo-360-auditor.md
21
- ```
22
-
23
- ### Étape 2 — Vérifier la config
24
-
25
- Assurez-vous que votre `_bmad/core/config.yaml` contient :
26
-
27
- ```yaml
28
- user_name: Laurent
29
- communication_language: French
30
- document_output_language: English
31
- output_folder: "{project-root}/_bmad-output"
32
- ```
33
-
34
- ### Étape 3 — Activer l'agent
35
-
36
- Demandez à votre IA :
37
- > _"Charge l'agent `_bmad/core/agents/seo-geo-360-auditor.md` et active-le"_
38
-
39
- L'agent affichera son menu avec les 8 commandes disponibles.
40
-
41
- ---
42
-
43
- ## Méthode 2 : Usage standalone (sans BMAD)
44
-
45
- ### Étape 1 — Copier le dossier complet
46
-
47
- ```
48
- Copiez le dossier entier :
49
- Audit SEO GEO 360/
50
-
51
- À la racine de votre projet :
52
- {votre-projet}/Audit SEO GEO 360/
53
- ```
54
-
55
- ### Étape 2 — Utiliser la checklist
56
-
57
- Ouvrez `checklist.md` et cochez les items un par un pendant votre audit.
58
-
59
- ### Étape 3 — Utiliser les templates
60
-
61
- Copiez les fichiers depuis `templates/` vers la racine web de votre site :
62
-
63
- | Template | Destination | Action |
64
- |---|---|---|
65
- | `templates/robots.txt` | `{site}/robots.txt` | Remplacez `YOUR-DOMAIN.com` |
66
- | `templates/llms.txt` | `{site}/llms.txt` | Remplissez les `[BRACKETS]` |
67
- | `templates/schema-templates.json` | Dans le `<head>` | Copiez les blocs JSON-LD nécessaires |
68
-
69
- ---
70
-
71
- ## Structure de dossiers
72
-
73
- ```
74
- votre-projet/
75
- ├── _bmad/
76
- │ └── core/
77
- │ ├── agents/
78
- │ │ ├── bmad-master.md
79
- │ │ └── seo-geo-360-auditor.md ← ICI (méthode BMAD)
80
- │ ├── config.yaml
81
- │ └── ...
82
- ├── website/ (ou public/, src/, etc.)
83
- │ ├── robots.txt ← Généré par l'agent
84
- │ ├── sitemap.xml ← Généré par l'agent
85
- │ ├── llms.txt ← Généré par l'agent
86
- │ └── index.php/html ← Schema.org injecté ici
87
- └── _bmad-output/
88
- └── seo-geo-audit-360.md ← Rapport d'audit généré
89
- ```
90
-
91
- ---
92
-
93
- ## Commandes rapides une fois l'agent activé
94
-
95
- | # | Commande | Ce que ça fait |
96
- |---|---|---|
97
- | `FA` | Audit complet 360° | Analyse tout et génère un rapport |
98
- | `GF` | Génère les fichiers | Crée robots.txt, sitemap, llms.txt, Schema |
99
- | `SC` | Scorecard | Scores rapides sur 10 par catégorie |
100
- | `FAQ` | Génère la FAQ | Section FAQ + FAQPage Schema bilingue |
101
- | `GA` | Audit GEO | Focus optimisation pour ChatGPT/Perplexity/Gemini |
102
-
103
- ---
104
-
105
- ## Projets compatibles
106
-
107
- Cet agent fonctionne avec **tout type de projet web** :
108
-
109
- - PHP (WordPress, Laravel, sites statiques)
110
- - JavaScript (Next.js, Nuxt, Vite, React)
111
- - HTML statique
112
- - Python (Django, Flask)
113
- - Sites JAMstack (Astro, Gatsby, Hugo)
114
-
115
- L'agent détecte automatiquement le framework et adapte ses recommandations.
@@ -1,66 +0,0 @@
1
- # SEO Engine v2.0 — BMAD+ SEO Audit 360
2
-
3
- > **By Laurent Rochetta** | Oveanet × BMAD+
4
-
5
- ## Overview
6
-
7
- A comprehensive SEO audit engine with 3 multi-role agents, a 6-phase workflow, Python toolkit, and auto-fix generation. Built from scratch for the BMAD+ framework.
8
-
9
- ## Agents
10
-
11
- | Agent | Roles | Purpose |
12
- |-------|-------|---------|
13
- | 🔎 **Scout** | Crawler, Inspector, Photographer | Technical scanning (9 categories) |
14
- | ⚖️ **Judge** | Content Expert, Schema Master, GEO Analyst | Content quality, E-E-A-T, AI readiness |
15
- | 👑 **Chief** | Scorer, Strategist, Reporter | Scoring (0-100), action plans, monitoring |
16
-
17
- ## Workflow (6 Phases)
18
-
19
- 1. **Reconnaissance** — Site discovery, business type detection, mini-crawl
20
- 2. **Deep Scan** — Scout + Judge in parallel (technical + content)
21
- 3. **AI Readiness** — GEO analysis for AI search visibility
22
- 4. **Scoring** — SEO Health Score (0-100) with weighted categories
23
- 5. **Action Plan** — Prioritized roadmap + auto-generated code fixes
24
- 5b. **PageSpeed Loop** — Iterative fixing to achieve 100% on all 4 categories
25
- 6. **Monitoring** — Score tracking over time
26
-
27
- ## Commands
28
-
29
- ```bash
30
- /seo full <url> # Complete 6-phase audit
31
- /seo quick <url> # Phases 1-4 only
32
- /seo technical <url> # Technical audit
33
- /seo content <url> # Content + E-E-A-T
34
- /seo geo <url> # AI search readiness
35
- /seo schema <url> # Schema validation
36
- /seo pagespeed <url> # PageSpeed perfection loop
37
- /seo plan <type> # Strategic plan (saas/ecommerce/local)
38
- /seo fix # Auto-generate fixes
39
- /seo history # Score history
40
- /seo compare # Compare with previous audit
41
- ```
42
-
43
- ## Python Toolkit
44
-
45
- | Script | Purpose |
46
- |--------|---------|
47
- | `seo_fetch.py` | Secure HTTP fetcher (SSRF protection, multi-UA) |
48
- | `seo_parse.py` | HTML parser (meta, schema, links, word count) |
49
- | `seo_crawl.py` | Recursive mini-crawler with sitemap discovery |
50
- | `seo_screenshot.py` | Playwright viewport screenshots + above-fold analysis |
51
-
52
- ## Scoring System
53
-
54
- | Category | Weight |
55
- |----------|--------|
56
- | Technical SEO | 20% |
57
- | Content & E-E-A-T | 22% |
58
- | On-Page SEO | 18% |
59
- | Schema | 10% |
60
- | Performance (CWV) | 12% |
61
- | AI Readiness (GEO) | 12% |
62
- | Images | 6% |
63
-
64
- ## License
65
-
66
- MIT — By Laurent Rochetta
@@ -1,70 +0,0 @@
1
- name: seo-audit-360
2
- version: 2.0.0
3
- author: Laurent Rochetta
4
- brand: Oveanet × Laurent Rochetta
5
- description: >
6
- SEO Engine v2.0 — Complete SEO audit system with 3 multi-role agents,
7
- 6-phase workflow, Python toolkit, and PageSpeed perfection loop.
8
- Covers technical SEO, E-E-A-T, schema validation, GEO (AI search),
9
- Core Web Vitals, and auto-fix generation.
10
-
11
- agents:
12
- - id: seo-scout
13
- name: Scout
14
- file: agent/seo-scout.md
15
- roles: [crawler, inspector, photographer]
16
- description: Technical scanner — crawl, fetch, inspect, screenshot
17
-
18
- - id: seo-judge
19
- name: Judge
20
- file: agent/seo-judge.md
21
- roles: [content-expert, schema-master, geo-analyst]
22
- description: Content & AI analyst — E-E-A-T, schema, GEO
23
-
24
- - id: seo-chief
25
- name: Chief
26
- file: agent/seo-chief.md
27
- roles: [scorer, strategist, reporter]
28
- description: Strategist & reporter — scoring, action plans, monitoring
29
-
30
- scripts:
31
- - seo_fetch.py
32
- - seo_parse.py
33
- - seo_crawl.py
34
- - seo_screenshot.py
35
-
36
- references:
37
- - ref/cwv-thresholds.md
38
- - ref/schema-catalog.md
39
- - ref/eeat-criteria.md
40
- - ref/geo-signals.md
41
- - ref/quality-gates.md
42
- - ref/schema-templates.json
43
-
44
- workflow: templates/seo-audit-workflow.md
45
-
46
- commands:
47
- - /seo full <url>
48
- - /seo quick <url>
49
- - /seo technical <url>
50
- - /seo content <url>
51
- - /seo geo <url>
52
- - /seo schema <url>
53
- - /seo images <url>
54
- - /seo hreflang <url>
55
- - /seo pagespeed <url>
56
- - /seo plan <type>
57
- - /seo fix
58
- - /seo history
59
- - /seo compare
60
-
61
- platforms: [bmad, claude, gemini, opencode, codex]
62
-
63
- dependencies:
64
- required:
65
- - python >= 3.10
66
- optional:
67
- - requests (pip install requests)
68
- - beautifulsoup4 (pip install beautifulsoup4)
69
- - lxml (pip install lxml)
70
- - playwright (pip install playwright && playwright install chromium)
@@ -1,79 +0,0 @@
1
- # Google Analytics 4 Extension — BMAD+ SEO Engine
2
-
3
- > Author: Laurent Rochetta | BMAD+ SEO Engine v2.1
4
-
5
- ## Overview
6
-
7
- This extension connects to Google Analytics 4 (GA4) Data API for organic traffic analysis. Uses the same OAuth2 credentials as the Search Console extension.
8
-
9
- ## Setup Guide
10
-
11
- ### Prerequisites
12
- - Google Cloud project with **GA4 Data API** enabled
13
- - OAuth2 credentials (same `credentials.json` as GSC extension)
14
- - GA4 property ID (find in GA4 Admin > Property Settings)
15
-
16
- ### First Run
17
- ```bash
18
- python ga4_client.py --setup --property 123456789
19
- ```
20
-
21
- ## Commands
22
-
23
- ```bash
24
- # Organic traffic overview
25
- python ga4_client.py --organic https://example.com --property 123456789 --days 30
26
-
27
- # Top organic landing pages
28
- python ga4_client.py --landing https://example.com --property 123456789 --days 30
29
-
30
- # Conversions from organic
31
- python ga4_client.py --conversions https://example.com --property 123456789 --days 30
32
-
33
- # Full export
34
- python ga4_client.py --all https://example.com --property 123456789 --json > ga4-data.json
35
- ```
36
-
37
- ## Output Examples
38
-
39
- ### Organic Traffic
40
- ```
41
- Organic Traffic (30 days):
42
- Sessions: 12,450
43
- Users: 8,230
44
- New Users: 6,120
45
- Engagement Rate: 72.3%
46
- Avg Duration: 2m 45s
47
- Bounce Rate: 36.1%
48
- ```
49
-
50
- ### Top Landing Pages
51
- ```
52
- Top Organic Landing Pages:
53
- 1. /blog/ai-development — 2,340 sessions, 78% engagement
54
- 2. / — 1,850 sessions, 65% engagement
55
- 3. /features — 1,120 sessions, 82% engagement
56
- ```
57
-
58
- ## Integration with SEO Engine
59
-
60
- When installed, the SEO Engine can:
61
- - Correlate crawled pages with actual organic traffic
62
- - Identify high-traffic pages that need SEO optimization
63
- - Track organic conversion attribution
64
- - Detect pages with high impressions but low engagement (content quality issues)
65
-
66
- ## Dependencies
67
-
68
- Same Google Auth libraries as GSC extension:
69
- ```
70
- google-auth>=2.0.0
71
- google-auth-oauthlib>=1.0.0
72
- google-analytics-data>=0.18.0
73
- ```
74
-
75
- ## Security Notes
76
-
77
- - Uses same `credentials.json` and `token.json` as GSC extension
78
- - GA4 property ID is not sensitive but should be stored per-project
79
- - Add credentials to `.gitignore`
@@ -1,200 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Google Analytics 4 Client — GA4 Data API client for organic traffic analysis.
4
-
5
- Features:
6
- - Organic traffic metrics (sessions, users, engagement)
7
- - Landing page performance
8
- - Conversion attribution
9
- - Custom date ranges
10
-
11
- Author: Laurent Rochetta
12
- License: MIT
13
- """
14
-
15
- import argparse
16
- import json
17
- import os
18
- import sys
19
- from datetime import datetime, timedelta
20
-
21
- SCOPES = ["https://www.googleapis.com/auth/analytics.readonly"]
22
- CREDENTIALS_FILE = os.path.join(os.path.dirname(__file__), "..", "google-search-console", "credentials.json")
23
- TOKEN_FILE = os.path.join(os.path.dirname(__file__), "..", "google-search-console", "token.json")
24
-
25
-
26
- def get_client(property_id: str):
27
- """Authenticate and return a GA4 BetaAnalyticsData client."""
28
- try:
29
- from google.oauth2.credentials import Credentials
30
- from google_auth_oauthlib.flow import InstalledAppFlow
31
- from google.auth.transport.requests import Request
32
- from google.analytics.data_v1beta import BetaAnalyticsDataClient
33
- from google.analytics.data_v1beta.types import (
34
- DateRange, Dimension, Metric, RunReportRequest, FilterExpression,
35
- Filter,
36
- )
37
- except ImportError:
38
- print(
39
- "Error: Missing dependencies. Install:\n"
40
- " pip install google-auth google-auth-oauthlib google-analytics-data",
41
- file=sys.stderr,
42
- )
43
- sys.exit(1)
44
-
45
- creds = None
46
- if os.path.exists(TOKEN_FILE):
47
- creds = Credentials.from_authorized_user_file(TOKEN_FILE, SCOPES)
48
-
49
- if not creds or not creds.valid:
50
- if creds and creds.expired and creds.refresh_token:
51
- creds.refresh(Request())
52
- else:
53
- if not os.path.exists(CREDENTIALS_FILE):
54
- print(f"Error: credentials.json not found. See EXTENSION.md for setup.", file=sys.stderr)
55
- sys.exit(1)
56
- flow = InstalledAppFlow.from_client_secrets_file(CREDENTIALS_FILE, SCOPES)
57
- creds = flow.run_local_server(port=0)
58
-
59
- with open(TOKEN_FILE, "w") as f:
60
- f.write(creds.to_json())
61
-
62
- return BetaAnalyticsDataClient(credentials=creds), property_id
63
-
64
-
65
- def run_organic_report(client, property_id: str, days: int = 30) -> dict:
66
- """Get organic traffic overview."""
67
- from google.analytics.data_v1beta.types import (
68
- DateRange, Metric, RunReportRequest, FilterExpression, Filter,
69
- )
70
-
71
- end_date = datetime.now().date()
72
- start_date = end_date - timedelta(days=days)
73
-
74
- request = RunReportRequest(
75
- property=f"properties/{property_id}",
76
- date_ranges=[DateRange(start_date=start_date.isoformat(), end_date=end_date.isoformat())],
77
- metrics=[
78
- Metric(name="sessions"),
79
- Metric(name="totalUsers"),
80
- Metric(name="newUsers"),
81
- Metric(name="engagementRate"),
82
- Metric(name="averageSessionDuration"),
83
- Metric(name="bounceRate"),
84
- ],
85
- dimension_filter=FilterExpression(
86
- filter=Filter(
87
- field_name="sessionDefaultChannelGroup",
88
- string_filter=Filter.StringFilter(value="Organic Search"),
89
- )
90
- ),
91
- )
92
-
93
- response = client.run_report(request)
94
-
95
- if not response.rows:
96
- return {"error": "No organic data available for this period"}
97
-
98
- row = response.rows[0]
99
- return {
100
- "sessions": int(row.metric_values[0].value),
101
- "users": int(row.metric_values[1].value),
102
- "new_users": int(row.metric_values[2].value),
103
- "engagement_rate": round(float(row.metric_values[3].value) * 100, 1),
104
- "avg_duration_seconds": round(float(row.metric_values[4].value)),
105
- "bounce_rate": round(float(row.metric_values[5].value) * 100, 1),
106
- }
107
-
108
-
109
- def run_landing_page_report(client, property_id: str, days: int = 30, limit: int = 20) -> list:
110
- """Get top organic landing pages."""
111
- from google.analytics.data_v1beta.types import (
112
- DateRange, Dimension, Metric, RunReportRequest, FilterExpression, Filter,
113
- OrderBy,
114
- )
115
-
116
- end_date = datetime.now().date()
117
- start_date = end_date - timedelta(days=days)
118
-
119
- request = RunReportRequest(
120
- property=f"properties/{property_id}",
121
- date_ranges=[DateRange(start_date=start_date.isoformat(), end_date=end_date.isoformat())],
122
- dimensions=[Dimension(name="landingPage")],
123
- metrics=[
124
- Metric(name="sessions"),
125
- Metric(name="engagementRate"),
126
- Metric(name="averageSessionDuration"),
127
- ],
128
- dimension_filter=FilterExpression(
129
- filter=Filter(
130
- field_name="sessionDefaultChannelGroup",
131
- string_filter=Filter.StringFilter(value="Organic Search"),
132
- )
133
- ),
134
- order_bys=[OrderBy(metric=OrderBy.MetricOrderBy(metric_name="sessions"), desc=True)],
135
- limit=limit,
136
- )
137
-
138
- response = client.run_report(request)
139
-
140
- return [{
141
- "page": row.dimension_values[0].value,
142
- "sessions": int(row.metric_values[0].value),
143
- "engagement_rate": round(float(row.metric_values[1].value) * 100, 1),
144
- "avg_duration": round(float(row.metric_values[2].value)),
145
- } for row in response.rows]
146
-
147
-
148
- # ── CLI ────────────────────────────────────────────────────────────
149
-
150
- def main():
151
- parser = argparse.ArgumentParser(
152
- description="Google Analytics 4 Client (BMAD+ SEO Engine)"
153
- )
154
- parser.add_argument("--property", "-p", required=True, help="GA4 Property ID")
155
- parser.add_argument("--organic", action="store_true", help="Organic traffic overview")
156
- parser.add_argument("--landing", action="store_true", help="Top landing pages")
157
- parser.add_argument("--all", action="store_true", help="All reports")
158
- parser.add_argument("--days", type=int, default=30, help="Days lookback (default: 30)")
159
- parser.add_argument("--limit", type=int, default=20, help="Max rows (default: 20)")
160
- parser.add_argument("--json", "-j", action="store_true", help="Output as JSON")
161
- parser.add_argument("--setup", action="store_true", help="Run OAuth2 setup")
162
-
163
- args = parser.parse_args()
164
-
165
- client, property_id = get_client(args.property)
166
-
167
- if args.setup:
168
- print("✅ OAuth2 setup complete for GA4.")
169
- return
170
-
171
- if args.organic or args.all:
172
- data = run_organic_report(client, property_id, args.days)
173
- if args.json:
174
- print(json.dumps({"organic": data}, indent=2))
175
- else:
176
- print(f"\nOrganic Traffic ({args.days} days):")
177
- if "error" in data:
178
- print(f" {data['error']}")
179
- else:
180
- mins = data["avg_duration_seconds"] // 60
181
- secs = data["avg_duration_seconds"] % 60
182
- print(f" Sessions: {data['sessions']:,}")
183
- print(f" Users: {data['users']:,}")
184
- print(f" New Users: {data['new_users']:,}")
185
- print(f" Engagement: {data['engagement_rate']}%")
186
- print(f" Avg Duration: {mins}m {secs}s")
187
- print(f" Bounce Rate: {data['bounce_rate']}%")
188
-
189
- if args.landing or args.all:
190
- pages = run_landing_page_report(client, property_id, args.days, args.limit)
191
- if args.json:
192
- print(json.dumps({"landing_pages": pages}, indent=2))
193
- else:
194
- print(f"\nTop Organic Landing Pages:")
195
- for i, p in enumerate(pages, 1):
196
- print(f" {i:2}. {p['page'][:55]} — {p['sessions']:,} sessions, {p['engagement_rate']}% engagement")
197
-
198
-
199
- if __name__ == "__main__":
200
- main()
@@ -1,4 +0,0 @@
1
- # Google Analytics 4 Extension — Dependencies
2
- google-auth>=2.0.0
3
- google-auth-oauthlib>=1.0.0
4
- google-analytics-data>=0.18.0