Gego is an open-source GEO (Generative Engine Optimization) tracker. It schedules prompts across multiple Large Language Models (LLMs), captures web-search citations from their responses, tracks brand mentions with aliases, and surfaces keyword and domain analytics through a built-in dashboard and CLI.
Website: getgego.org
- Multi-LLM support: OpenAI, Anthropic, Ollama, Google, Perplexity (Sonar), and pluggable custom providers
- Built-in web dashboard (
gego-ui): Vue 3 dashboard for stats, search, models, prompts, scheduler, words, and error logs - Brand tracking: Canonical brands with aliases; brand trends and citation-domain analytics on the dashboard
- Citation tracking: Extracts cited URLs and domains from provider web-search results (OpenAI, Anthropic, Google, Perplexity)
- Keyword analytics: Automatic keyword extraction with exclusion words managed in the database and UI
- Hybrid database: PostgreSQL for configuration, auth, brands, and schedules; MongoDB for prompts, responses, and analytics (SQLite supported for legacy deployments only)
- Distributed scheduling: Cron-based scheduler enqueues jobs to etcd; separate worker processes execute LLM calls
- JWT authentication: Role-based access (
admin,member) with session refresh - Flexible scheduling: Cron schedules, manual runs, run history, job retry, and cancellation
- Prompt generation: AI-assisted prompt creation via the API
- Tag-based filtering: Organize prompts with tags and filter dashboard/search stats
- Error logs: Review failed scheduled LLM calls (rate limits, provider errors)
- CLI and REST API: Full management from the terminal or HTTP
- Retry mechanism: Automatic retry with delays for failed requests
- Configurable logging: DEBUG, INFO, WARNING, ERROR levels with optional file output
- Docker-ready: Single image bundles the API and pre-built UI
- GEO / brand visibility: Track how your brand and competitors appear in AI-generated answers
- Citation analysis: See which domains and URLs LLMs cite most often for your prompts
- Brand mapping: Normalize detected brand spellings and aliases to canonical names
- SEO and marketing research: Monitor keyword mentions across AI assistants
- Competitive analysis: Compare visibility across providers and models
- Prompt engineering: Identify which prompts drive the most mentions and citations
- Go 1.25 or higher
- Node.js 20.19+ or 22.12+ (for UI development)
- PostgreSQL (relational data: LLMs, schedules, users, brands, exclusion words)
- MongoDB (prompts, responses, analytics)
- etcd (job queue for scheduled and manual runs; required when starting the API)
- API keys for LLM providers (OpenAI, Anthropic, etc.)
git clone https://github.com/AI2HU/gego.git
cd gego
make buildThe binary is written to build/gego.
go install github.com/AI2HU/gego/cmd/gego@latestThe production image builds the UI and API into one container. The dashboard is served at the same port as the API.
For deployment details, see DEPLOYMENT.md
docker build -t gego:latest .
docker run -d \
--name gego \
-p 8989:8989 \
-e GEGO_POSTGRES_URI=postgres://user:pass@your-postgres-host:5432/gego?sslmode=disable \
-e GEGO_MONGODB_URI=mongodb://your-mongodb-host:27017 \
-e GEGO_MONGODB_DATABASE=gego \
-e GEGO_JWT_SECRET="your-secret-at-least-32-characters-long" \
-e GEGO_BOOTSTRAP_ADMIN_PASSWORD="your-admin-password" \
gego:latestDocker environment variables
| Variable | Description |
|---|---|
GEGO_CONFIG_PATH |
Config file path (default: /app/config/config.yaml) |
GEGO_DATA_PATH |
Legacy SQLite data directory (default: /app/data) |
GEGO_LOG_PATH |
Log directory (default: /app/logs) |
GEGO_POSTGRES_URI |
PostgreSQL connection string |
GEGO_MONGODB_URI |
MongoDB connection string |
GEGO_MONGODB_DATABASE |
MongoDB database name (default: gego) |
GEGO_ETCD_ENDPOINTS |
Comma-separated etcd endpoints (default: 127.0.0.1:2379) |
GEGO_JWT_SECRET |
JWT signing secret (min 32 characters, required) |
GEGO_BOOTSTRAP_ADMIN_USERNAME |
First admin username (default: admin) |
GEGO_BOOTSTRAP_ADMIN_PASSWORD |
First admin password (min 8 characters, required on first run) |
GEGO_COOKIE_SECURE |
Set to true to mark auth cookies as Secure |
Copy .env.dev.example to .env.dev, start PostgreSQL, MongoDB, and etcd, then:
# Terminal 1 — local etcd
make etcd-dev
# Terminal 2 — API + embedded UI with dev fixtures
cp .env.dev.example .env.dev # first time only
make devmake dev builds the UI, loads dev database fixtures (sample LLMs, prompts, responses, brands), and starts the API with the embedded dashboard. Fixtures are enough to exercise the dashboard and search UI without running a worker.
To execute scheduled or manual prompt runs, also start a worker:
# Terminal 3 — schedule worker (requires etcd)
make dev-worker| Service | URL |
|---|---|
| Dashboard | http://localhost:8989 |
| API | http://localhost:8989/api/v1 |
Sign in with your bootstrap admin credentials (default username: admin; default dev password when using make dev: admin1234).
For manual setup without fixtures, or hot-reload UI development:
# 1. Initialize Gego (first time only)
./build/gego init
# 2. Build CLI and UI
make build
make ui-build
# 3. Set auth env vars (required for the API)
export GEGO_JWT_SECRET="your-secret-at-least-32-characters-long"
export GEGO_BOOTSTRAP_ADMIN_PASSWORD="your-admin-password"
# 4. Start etcd, then API with embedded UI (no fixture reload)
make etcd-dev # separate terminal
make dev-apimake etcd-dev # Terminal 1 — etcd on :2379
make dev-api # Terminal 2 — API on http://localhost:8989
make ui-dev # Terminal 3 — Vite on http://localhost:5173 (proxies /api to the API)
make dev-worker # Terminal 4 — optional, for schedule executionSee gego-ui/.env.example for optional UI environment variables.
The dashboard lives in gego-ui/ and is included in the repository.
| Page | Path | Description |
|---|---|---|
| Dashboard | / |
Brand trends, keyword stats, provider distribution, top cited domains, brand citation domains |
| Search | /search |
Full-text keyword search across stored responses |
| Models | /admin/models |
Manage LLM provider configurations |
| Prompts | /admin/prompts |
Create, tag, and filter prompt templates |
| Scheduler | /admin/scheduler |
Cron schedules, run history, and background scheduler control |
| Words | /admin/words |
Manage exclusion words and map detected brand words to canonical names |
| Logs | /admin/logs |
Failed LLM executions from scheduled runs |
Admin pages require the admin role. Members can access dashboard and search.
The API uses JWT access tokens with refresh-token rotation stored in PostgreSQL.
Bootstrap the first admin (when no users exist):
export GEGO_JWT_SECRET="your-secret-at-least-32-characters-long"
export GEGO_BOOTSTRAP_ADMIN_PASSWORD="your-admin-password"
./build/gego apiOr create users manually:
./build/gego user create --username admin --password "your-password" --role admin
./build/gego user listRoles
| Role | Access |
|---|---|
admin |
Full read/write on models, prompts, schedules, words/brands, stats, search, logs |
member |
Read-only on models/prompts/schedules; dashboard, stats, and search |
Auth endpoints (public unless noted)
POST /api/v1/auth/login— obtain tokensPOST /api/v1/auth/refresh— rotate access tokenPOST /api/v1/auth/logout— invalidate sessionGET /api/v1/auth/me— current user (authenticated)
All other /api/v1/* routes require a valid Authorization: Bearer <token> header.
gego initInteractive setup for PostgreSQL and MongoDB connections.
gego llm addSupported providers include OpenAI, Anthropic, Ollama, Google (Gemini), and Perplexity (Sonar).
gego prompt addPrompts support tags for filtering dashboard and search results.
gego schedule addCron expressions run selected prompts against selected models automatically.
gego run # Run all enabled prompts with all enabled LLMs once (direct execution)Schedule execution uses etcd for the job queue and worker processes for LLM calls.
make etcd-dev # Terminal 1: local etcd on :2379
make dev-worker # Terminal 2: job worker
gego scheduler start # Terminal 3: cron enqueuer (requires etcd)Required env: GEGO_ETCD_ENDPOINTS (default 127.0.0.1:2379).
gego api # Default: 0.0.0.0:8989
gego api --port 3000 # Custom port
gego api --cors-origin "https://myapp.com"When gego-ui/dist exists (or /app/ui in Docker), the API also serves the dashboard as static files.
gego db upgrade-from-sqlite --postgres-uri "postgres://localhost:5432/gego?sslmode=disable"Or use the in-app upgrade flow at /upgrade when the API detects a pending migration.
Base URL: http://localhost:8989/api/v1
GET /health— health check (public)
POST /auth/login,POST /auth/refresh,POST /auth/logoutGET /auth/me
GET /upgrades— list required database upgrades (public)POST /upgrades— run a pending upgrade (public)
GET /providers— list supported LLM providersGET /providers/:provider/api-keys— list stored API keys for a providerPOST /providers/:provider/models— list models available from a providerGET /models,GET /models/:id,POST /models,PUT /models/:id,DELETE /models/:id
GET /prompts,GET /prompts/:id,POST /prompts,PUT /prompts/:id,DELETE /prompts/:idPOST /prompts/generate— AI-assisted prompt generation
GET /schedules,GET /schedules/:id,POST /schedules,PUT /schedules/:id,DELETE /schedules/:idPOST /schedules/:id/run— enqueue a schedule run (202, returnsrun_id)GET /schedule-runs,GET /schedule-runs/:id,GET /schedule-runs/:id/jobsPOST /schedule-runs/:id/cancel,POST /schedule-runs/:id/jobs/:job_id/retryGET /scheduler/status,GET /scheduler/health,POST /scheduler/start,POST /scheduler/stop,POST /scheduler/reload
GET /stats— dashboard stats (keywords, brand trends, provider breakdown)GET /stats/urls— top cited URLs and domainsGET /stats/query-urls— URLs grouped by search queryGET /stats/keyword-domains— keyword × domain matrixGET /stats/brand-citation-domains— domains cited near selected brand mentionsPOST /search— keyword search across responses
GET /exclusion-words,POST /exclusion-words,DELETE /exclusion-words/:idGET /brands,POST /brands,PUT /brands/:id,DELETE /brands/:idGET /brands/suggestions— detected brand word suggestionsPOST /brands/map— map a detected word to a canonical brandPOST /brands/:id/aliases,PUT /brands/:id/aliases/:aliasId,DELETE /brands/:id/aliases/:aliasId
GET /logs/errors— failed LLM calls from scheduled executions
Example
curl http://localhost:8989/api/v1/health
curl -X POST http://localhost:8989/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"your-password"}'
curl http://localhost:8989/api/v1/stats \
-H "Authorization: Bearer <access_token>"More examples: EXAMPLES.md
gego stats keywords --limit 20
gego stats keyword Dior
gego stats refresh # reload exclusion words cache from the databasegego llm list
gego prompt list
gego schedule list
gego schedule run <id>
gego scheduler status
gego worker startConfiguration is stored in ~/.gego/config.yaml (or via environment variables):
sql_database:
provider: postgres
uri: postgres://localhost:5432/gego?sslmode=disable
database: gego
nosql_database:
provider: mongodb
uri: mongodb://localhost:27017
database: gego
auth:
issuer: gego-api
audience: gego-api
access_token_ttl: 15m
refresh_token_ttl: 168hEnvironment overrides (commonly used in Docker and make dev):
| Variable | Purpose |
|---|---|
GEGO_POSTGRES_URI |
PostgreSQL connection string |
GEGO_MONGODB_URI |
MongoDB connection string |
GEGO_MONGODB_DATABASE |
MongoDB database name |
GEGO_ETCD_ENDPOINTS |
etcd endpoints for the job queue |
Database architecture
| Store | Contents |
|---|---|
| PostgreSQL | LLM configs, schedules, users, sessions, brands, exclusion words |
| MongoDB | Prompts, responses (including search_urls citations), analytics |
| SQLite | Legacy deployments only — migrate with gego db upgrade-from-sqlite |
Exclusion words are stored in PostgreSQL and managed from the Words admin page or the API. On first startup, Gego can import words from the legacy file at ~/.gego/keywords_exclusion (one word per line; # for comments) when the database table is empty.
Optional provider-specific system prompts in config.yaml:
gemini_system_instructionchatgpt_system_instructionclaude_system_instruction
| Target | Description |
|---|---|
make build |
Build the CLI to build/gego |
make ui-install |
Install gego-ui npm dependencies |
make ui-build |
Build the dashboard to gego-ui/dist |
make ui-dev |
Vite dev server with hot reload (port 5173) |
make dev |
Build UI, load dev fixtures, start API with embedded static UI (port 8989) |
make fixtures-dev |
Reset and load dev database fixtures only (see CONTRIBUTING.md) |
make dev-api |
Start API only (port 8989); requires etcd |
make dev-worker |
Start schedule worker (requires etcd) |
make etcd-dev |
Run local etcd in Docker on port 2379 |
make test |
Run Go tests |
make build-all |
Cross-platform binaries |
Control verbosity with --log-level (DEBUG, INFO, WARNING, ERROR) and optional --log-file:
gego run --log-level DEBUG
gego api --log-level INFO --log-file /var/log/gego/app.logFailed prompt executions are retried up to 3 times with a 30-second delay between attempts.
Minimum runtime stack (API + worker + data stores):
flowchart LR
UI["gego-ui"] --> API["API + scheduler"]
API --> PG[(PostgreSQL)]
API --> Mongo[(MongoDB)]
API --> Etcd[(etcd)]
Worker["Worker"] --> Etcd
Worker --> PG
Worker --> Mongo
Worker --> LLMs["LLM providers"]
| Component | Role |
|---|---|
| gego-ui | Dashboard (served by the API, or Vite in local UI-only mode) |
| API + scheduler | REST API, auth, cron enqueue into etcd |
| Worker | Pulls jobs from etcd and runs LLM calls |
| PostgreSQL | Users, LLMs, schedules, brands, sessions |
| MongoDB | Prompts, responses, citations, analytics |
| etcd | Job queue between scheduler and workers |
LLM providers return SearchURLs alongside response text. Citations are stored on each response and aggregated for domain/URL stats. Brand aliases normalize detected mentions before stats are computed.
Implement the llm.Provider interface:
type Provider interface {
Name() string
Generate(ctx context.Context, prompt string, config Config) (*Response, error)
Validate(config map[string]string) error
ListModels(ctx context.Context, apiKey, baseURL string) ([]models.ModelInfo, error)
}Register your provider in the LLM registry (see internal/services/llm_registry.go).
Contributions are welcome.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes
- Push to the branch
- Open a Pull Request
See CONTRIBUTING.md for details.
- Persona embedding to simulate chat-style model behavior
- Schedule run-time estimation and cost forecasting
- Prompt batches to optimize costs
- Provider-specific prompt threading for speed
- Export statistics to CSV/JSON
- Webhook notifications
- Custom keyword extraction rules
- Time-series trend analysis
This project is licensed under the GNU General Public License v3.0 — see the LICENSE file for details.
- Cobra — CLI framework
- Gin — HTTP API
- Vue — dashboard UI
- etcd — distributed job queue
- MongoDB Go Driver — analytics database
- pgx — PostgreSQL driver
- robfig/cron — scheduling
- Website: getgego.org
- Email: jonathan@ai2h.tech
- Issues: GitHub Issues
- Discussions: GitHub Discussions
Made with care for the open-source community