Files
adsPRO/docs/unit-price.md
2026-05-05 21:46:26 +02:00

7.0 KiB
Raw Blame History

Unit Pricing — specyfikacja rozszerzenia adsPRO

Cel: dodać do adsPRO obsługę pól unit_pricing_measure i unit_pricing_base_measure (Google Merchant Center) tak, żeby moduł 14 audytu Google Ads (analiza-produkty) mógł je zapisywać z poziomu agenta AI, analogicznie do title / google_product_category / custom_label_*.

Kontekst: Google Merchant Center wymaga unit_pricing_measure dla kategorii kosmetyki/Health & Beauty. Brak tego pola = 894/3455 SKU u klienta aruba.rzeszow.pl z warning missing_potentially_required_attribute (servability=unaffected, ale ranking ↓ i brak wyświetlania ceny per ml/g).


1. Model danych (DB)

1.1 Tabela products — nowe kolumny

ALTER TABLE products
  ADD COLUMN unit_pricing_measure        VARCHAR(64)  NULL,  -- np. "30 ml", "100 g", "1 szt"
  ADD COLUMN unit_pricing_base_measure   VARCHAR(64)  NULL,  -- np. "100 ml", "1 kg", "1 szt"
  ADD COLUMN unit_pricing_changed_at     DATETIME     NULL;

Walidacja wartości (po stronie API i UI):

  • Format: <liczba><spacja><jednostka> — regex ^\d+(\.\d+)?\s+(ml|l|g|kg|szt|cm|m)$
  • Dozwolone jednostki (Google specyfikacja): ml, l, mg, g, kg, cl, m, cm, sqm, cbm, ct (count = sztuki — Google używa ct lub osobnego pola; w PL przyjąć szt).
  • unit_pricing_base_measure musi być w tej samej jednostce co measure (np. measure=30 ml → base=100 ml, NIE 1 l).
  • Standardowe wartości base: dla ml/g → 100, dla l/kg → 1, dla szt → 1.

1.2 Migracja

migrations/YYYY-MM-DD_add_unit_pricing.sql — patrz folder migrations/ projektu.


2. API publiczne (rozszerzenie api.php)

2.1 action=product_unit_pricing_set — zapis

Wzór: kopia product_custom_label_4_set z linii ~336 api.php.

Parametry:

  • api_key (string, wymagany)
  • client_id (int, wymagany)
  • offer_id (string, wymagany)
  • unit_pricing_measure (string, opcjonalny — pusta wartość czyści pole)
  • unit_pricing_base_measure (string, opcjonalny — j.w.)

Logika:

  • Walidacja regex (jw.) — jeśli zła forma → 422 Invalid unit_pricing_measure format.
  • Walidacja zgodności jednostek (measure unit == base unit) → 422 jeśli niezgodne.
  • Update products.unit_pricing_measure + unit_pricing_base_measure + unit_pricing_changed_at = NOW().
  • Wpis w products_comments: 'Zmiana unit_pricing na <m> / <b> (API)'.
  • HTTP 200 + JSON {result: ok, product_id, offer_id, unit_pricing_measure, unit_pricing_base_measure}.

Przykład:

curl -X POST https://adspro.projectpro.pl/api.php \
  -d action=product_unit_pricing_set \
  -d api_key=YOUR_KEY \
  -d client_id=3 \
  -d offer_id=7792 \
  -d unit_pricing_measure="30 ml" \
  -d unit_pricing_base_measure="100 ml"

2.2 action=product_unit_pricing_get — odczyt

Wzór: kopia product_custom_label_4_get.

Parametry: api_key, client_id, offer_id.

Odpowiedź:

{
  "result": "ok",
  "product_id": 987,
  "offer_id": "7792",
  "unit_pricing_measure": "30 ml",
  "unit_pricing_base_measure": "100 ml"
}

2.3 action=products_get_missing_unit_pricing — listing kandydatów (opcjonalne)

Cel: agent może pobrać top N produktów które wymagają unit_pricing (filtr per kategoria) — zamiast skanować per-product.

Parametry: api_key, client_id, opcjonalnie top (default 50), category_filter (np. Skin Care).

Logika: SELECT z products WHERE unit_pricing_measure IS NULL AND (kategoria w listy beauty/cosmetics) ORDER BY clicks_all_time DESC LIMIT N.

Odpowiedź: {result: ok, count: N, products: [{offer_id, default_name, custom_title, google_product_category, clicks_30, ...}]}.


3. Custom feed (zapis do GMC)

Lokalizacja: feeds/ w projekcie. Generator feedu produktowego musi dodać:

<g:unit_pricing_measure>30 ml</g:unit_pricing_measure>
<g:unit_pricing_base_measure>100 ml</g:unit_pricing_base_measure>

tylko gdy oba pola niepuste w bazie. Pominąć tag jeśli null/empty (Google nie akceptuje pustych wartości).


4. Heurystyka AI (po stronie agenta — NIE w adsPRO)

Agent (np. set_product_unit_pricing.py w projekcie D:\google ads\scripts\actions\) wyciąga measure z tytułu produktu:

Wzorzec w tytule measure base
... 30ml lub ... 30 ml 30 ml 100 ml
... 1000ml lub ... 1l 1000 ml 100 ml
... 100g 100 g 100 g
... 1kg 1 kg 1 kg
... 10szt 10 szt 1 szt

Edge cases (do flagowania jako "wątpliwości" — agent pyta usera):

  • Multi-component (zestaw 3 płynów × 200ml) — brak jednoznacznej miary
  • Sprzęt (fotel, taboret) — N/A jednostka
  • Nieznana pojemność (np. tylko nr 3)

5. Acceptance criteria

  • Migracja DB dodaje 3 kolumny + indeks na unit_pricing_measure IS NULL
  • api.php ma 3 nowe endpointy (_set, _get, _get_missing — ostatni opcjonalny)
  • Walidacja formatu regex + jednostek (testy unit)
  • Generator feedu zapisuje <g:unit_pricing_measure> + <g:unit_pricing_base_measure> gdy oba pola wypełnione
  • product_unit_pricing_set zapisuje wpis do products_comments
  • product_unit_pricing_set aktualizuje unit_pricing_changed_at
  • Endpoint _get_missing filtruje po kategorii (beauty/cosmetics) i sortuje po klikach
  • Skrypt set_product_unit_pricing.py po stronie agenta (D:\google ads\scripts\actions\) — wzorzec z set_product_custom_label.py
  • Skrypt apply_unit_pricing_from_previews.py — batch zapis z tabel preview w raportach M14 (klienci/<dom>/.analysis/reports/analiza-produkty-*.md — etap 1.5)

6. Pilotaż

Klient pilotażowy: aruba.rzeszow.pl (client_id=3).

Pierwsza partia (5 SKU z preview M14 z 2026-05-05):

product_id unit_pricing_measure unit_pricing_base_measure
7792 30 ml 100 ml
305 10 ml 100 ml
35 60 ml 100 ml
281 100 ml 100 ml
2288 1000 ml 100 ml

Sukces pilotażu = 5/5 SKU widocznych w GMC z polami unit_pricing po 24h od pierwszego push feedu.


7. Dokumentacja publiczna

Po wdrożeniu: dopisać sekcję 4.X do docs/api-public-product-management.md (analogicznie do sekcji 4.7 product_custom_label_4_set):

  • 4.X.1 product_unit_pricing_set
  • 4.X.2 product_unit_pricing_get
  • 4.X.3 (opc.) products_get_missing_unit_pricing

8. TODO procesowe (po wdrożeniu)

  1. Backfill agentem AI wszystkich istniejących produktów z brakiem unit_pricing — heurystyka z sekcji 4 + flag wątpliwości na liście do user review.
  2. Skrypt apply_unit_pricing_from_previews.py w projekcie agenta — batch zapis tabel preview z M14 raportów (etap 1.5) dla wszystkich klientów.
  3. Monitoring w analiza-feed (M2): sprawdzanie liczby SKU bez unit_pricing — cel <5% per klient w branżach beauty/cosmetics.

9. Powiązane

  • Kontekst dla agenta: D:\google ads\.claude\commands\analiza-produkty.md — sekcja "Etap 1.5: Unit pricing (preview)".
  • Pierwsza preview tabela: D:\google ads\klienci\aruba.rzeszow.pl\.analysis\reports\analiza-produkty-2026-05-05.md.