# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project Overview adsPRO is a PHP web application for managing Google Ads, Facebook Ads, and Google Merchant Center campaigns. It tracks campaign performance (ROAS, budgets, conversions), manages product feeds, and provides AI-powered suggestions for product titles/descriptions. The UI is in Polish. ## Tech Stack - **PHP** (no framework, custom MVC-like architecture) - **MySQL** via Medoo ORM (`$mdb` global) and RedBeanPHP (`\R::`) in legacy endpoints - **Frontend**: jQuery, DataTables, Highcharts, Select2, Bootstrap 5, Font Awesome 6 - **SCSS** for styling (`layout/style.scss` → `layout/style.css`) - **Google Ads REST API** v23 (direct cURL, no SDK) - **Facebook Ads Graph API** (direct cURL) - **AI services**: OpenAI, Claude, Gemini APIs for product text suggestions ## Architecture ### Request Flow `index.php` is the single entry point. `.htaccess` rewrites all non-static requests to it. The router uses a `$route_aliases` map and fallback URL segment parsing (`/module/action`) to set `$_GET['module']` and `$_GET['action']`. `\controls\Site::route()` instantiates `\controls\{Module}` and calls the action method. Other entry points: - `ajax.php` — AJAX requests (same autoloader, session-based auth with IP binding) - `api.php` — external API endpoints (domain tester, Open Page Rank) - `cron.php` — legacy cron (task reminders, recurring tasks) ### Autoloader & Namespace Convention `spl_autoload_register` maps namespaces to filesystem paths: - `\controls\Campaigns` → `autoload/controls/class.Campaigns.php` - `\factory\Clients` → `autoload/factory/class.Clients.php` - `\services\GoogleAdsApi` → `autoload/services/class.GoogleAdsApi.php` - `\view\Site` → `autoload/view/class.Site.php` File naming: `class.{ClassName}.php`. Root-level classes (no namespace): `autoload/class.{Name}.php`. ### Layer Responsibilities - **`autoload/controls/`** — Controllers. Handle request params via `\S::get()`, call factory/services, return HTML (via `\Tpl::view()`) or `echo json_encode()` + `exit` for AJAX. - **`autoload/factory/`** — Data access layer. Static methods wrapping `$mdb` queries. Named after domain entities (Clients, Campaigns, Products, etc.). - **`autoload/services/`** — External API integrations (GoogleAdsApi, FacebookAdsApi, ClaudeApi, OpenAiApi, GeminiApi, SupplementalFeed). - **`autoload/view/`** — View helpers. Thin wrappers that call `\Tpl::view()` with template path and data. - **`templates/{module}/`** — PHP template files rendered by `Tpl::view()`. Templates access data via `$this->varName`. ### Key Base Classes - **`\S`** — Static utility: `get()` reads POST/GET, `get_session()`/`set_session()` for sessions, `alert()` for flash messages, `send_email()` for SMTP. - **`\Tpl`** — Template engine. `Tpl::view('module/template', [...])` renders `templates/module/template.php`. Looks in `templates_user/` first (override), then `templates/`. - **`\DbModel`** — Active Record base class. Subclasses set `$table`; provides `save()`, `delete()`. - **`\Cache`** — File-based cache in `temp/` directory. `Cache::store($key, $data, $ttl)` / `Cache::fetch($key)`. ### Settings Storage App settings (API keys, cron state, feature flags) are stored in a `settings` DB table as key-value pairs. Access via `\services\GoogleAdsApi::get_setting($key)` / `set_setting($key, $value)` — these are used globally, not just for Google Ads. ## Database Migrations Numbered SQL files in `migrations/` (e.g., `001_google_ads_settings.sql`). Run via: ```bash php install.php # apply pending migrations php install.php --force # re-apply all migrations php install.php --with_demo # include demo_data.sql ``` Tracks applied migrations in `schema_migrations` table. ## Cron System Multiple cron endpoints called externally (e.g., every 1-5 minutes): | Endpoint | Purpose | |---|---| | `/cron.php` | Legacy: task reminders, recurring tasks | | `/cron/cron_universal` | Google Ads campaigns + products sync (backfill window) | | `/cron/cron_campaigns_product_alerts_merchant` | Product alerts from Merchant Center | | `/cron/cron_products_urls` | Fetch product URLs from Merchant Center | | `/cron/cron_facebook_ads` | Facebook Ads sync (30-day window) | Progress is tracked in `cron_sync_status` table with phases (pending → fetch → aggregate_30 → done). Dashboard at `/settings` shows real-time progress with ETA calculations. ## Supplemental Feeds `\services\SupplementalFeed::generate_for_client($id)` generates TSV files in `feeds/` directory (e.g., `feeds/supplemental_1.tsv`) for Google Merchant Center. Managed via `/feeds` UI. ## Coding Conventions - All classes use static methods extensively - Database access uses the global `$mdb` (Medoo instance) — never instantiate a new connection - AJAX endpoints: `echo json_encode([...])` then `exit` - Page actions: return HTML string from `\Tpl::view()` - POST/GET params: always use `\S::get('param_name')`, never `$_POST`/`$_GET` directly - Flash messages: `\S::alert('message')` then `header('Location: ...')` + `exit` - Timezone: `Europe/Warsaw` - Currency display: `\S::number_display($value)` formats as "1 234,56 zł" - All user-facing strings are in Polish ## Adding a New Module 1. Create controller: `autoload/controls/class.{ModuleName}.php` (namespace `controls`) 2. Create factory: `autoload/factory/class.{ModuleName}.php` (namespace `factory`) 3. Optionally create view helper: `autoload/view/class.{ModuleName}.php` (namespace `view`) 4. Create templates: `templates/{module_name}/main_view.php` etc. 5. Add route aliases in `index.php` `$route_aliases` array if clean URLs are needed 6. Add sidebar link in `templates/site/layout-logged.php` ## Frontend Libraries (in `libraries/`) - `medoo/` — Medoo PHP database framework (SQL builder) - `rb.php` — RedBeanPHP ORM (used in legacy `api.php`, `cron.php`) - `phpmailer/` — Email sending - `framework/` — jQuery UI, Bootstrap, various jQuery plugins - `functions.js` — Shared JS utilities - `adspro-dialog.js/.css` — Custom modal dialog component