← всі звіти · read-2026-04-30T133848Z-tabletki-pipeline-v2.md

Tabletki.ua Sales Pipeline — VPS Handoff

Дата: 2026-04-30 Автор: Cowork session (Serhii / Delta Medical) Призначення: Claude на VPS має змогу самостійно перевіряти та завантажувати дані продажів і UTM-аналітику з Tabletki.ua в BigQuery.


1. Архітектура

Tabletki.ua API (cab-producer.tabletki.ua)
        │
        ├─ reportId: 4ed497e3...  (Продажі)
        │       ▼
        │  tabletki-sales-loader.js
        │       ▼
        │  BQ: tabletki.tabletki_sales (393+ rows)
        │       ▼  Views → Looker Studio
        │
        └─ reportId: 72c243dc...  (UTM мітки)
                ▼
           tabletki-utm-loader.js
                ▼
           BQ: tabletki.tabletki_utm (22+ rows)

Проект GCP: ad-analytics-hub Dataset: tabletki (region: EU) Таблиці: tabletki_sales, tabletki_utm


2. Файли проекту

Розташування на робочому ПК:

D:\Users\Sergey.Vereschak.DELTAMEDICAL\Documents\Claude\Projects\Ads Analyser\
Файл Опис
tabletki-sales-loader.js Node.js loader продажів — 3 режими: api, excel, backfill
tabletki_sales_schema.json BigQuery schema продажів (20 полів)
tabletki-utm-loader.js Node.js loader UTM-звіту — API fetch, ChildArray flatten, BQ upsert
tabletki_utm_schema.json BigQuery schema UTM (10 полів)
utm_insert.sql SQL для ручного створення таблиці + INSERT даних
.env.example Шаблон змінних середовища
looker_studio_views.sql 4 SQL views для Looker Studio
tabletki_sales_*.ndjson Приклад завантажених даних продажів
tabletki_utm_*.ndjson Приклад завантажених UTM-даних

3. Credentials (що потрібно)

3a. Tabletki.ua API Token

3b. Google Cloud / BigQuery


4. API Reference

Base URL: https://cab-producer.tabletki.ua Swagger: https://cab-producer.tabletki.ua/report-swagger/

Головний ендпоінт

POST /api/ReportExecution/report?reportType=JSON&reportId={uuid}
Authorization: Bearer {TABLETKI_TOKEN}
Content-Type: application/json

Body: { "dateFrom": "2026-04-12", "dateTo": "2026-04-12" }

Додаткові body поля (optional): periodType, sku, area, city, tableSku

Report IDs

ID Назва
4ed497e3-2e47-11ef-9209-000c29baf0b7 Продажі по категоріям ← основний
3f8a03b8-1f1b-11ef-9209-000c29baf0b7 Продажі по ATC-групам
dbc1d89c-4579-11ef-920a-000c29baf0b7 По категоріям (по містах)
dbc1d89d-4579-11ef-920a-000c29baf0b7 По категоріям (по областях)
5d2bb5bd-4989-11ef-920a-000c29baf0b7 Динаміка по категоріям
a65e7e0a-b7ba-11ef-9210-000c29baf0b7 Динаміка замовлень погодинна
72c243dc-7f5a-11f0-9225-000c29baf0b7 Звіт за UTM мітками
730778ee-6168-11f0-9225-000c29baf0b7 Заблоковані товари
351afe8f-7cee-11f0-9225-000c29baf0b7 Якість бронювання

JSON Response Fields (salesByCategory)

SkuId → sku_id, SkuCode → product_code, SkuName → product_name,
SkuProducer → manufacturer, CategoryCode → category_code,
Category → category_name, Qty → units_sold, SaleSum → revenue_uah,
AvgPrice → avg_price_uah, CatSaleSum → category_revenue_uah,
Weight → pct_category_revenue, WeightQty → pct_category_units,
QtyTop1/2/3 → category_top1/2/3_units

Інші ендпоінти

Важливо: MVC ендпоінти (/Report/GetReport, /Report/Download) НЕ працюють з Bearer token — тільки /api/* ендпоінти.


5. Використання loader

Встановлення залежностей

npm install dotenv @google-cloud/bigquery xlsx axios

Режими запуску

# Одноразове завантаження (один період)
node tabletki-sales-loader.js --mode=api --from=2026-04-21 --to=2026-04-27

# Завантаження з Excel файлу
node tabletki-sales-loader.js --mode=excel --file="path/to/report.xlsx"

# Backfill (автоматична розбивка на чанки)
node tabletki-sales-loader.js --mode=backfill --from=2026-01-01 --to=2026-04-27 --period=week

UTM Loader

# Одноразове завантаження UTM-звіту
node tabletki-utm-loader.js --from=2026-04-23 --to=2026-04-29

# Dry run (тест без запису в BQ)
node tabletki-utm-loader.js --from=2026-04-23 --to=2026-04-29 --dry-run

# Зберегти як NDJSON
node tabletki-utm-loader.js --from=2026-04-23 --to=2026-04-29 --out-ndjson=utm_data.ndjson

UTM Response — flatten logic

API повертає масив кампаній. Кожна кампанія має поле ChildArray (JSON string) з розбивкою по source/medium. Loader розгортає (flatten) ChildArray: кожна комбінація campaign/source/medium = окремий рядок.

Маппінг полів з ChildArray:

Utm Source       → utm_source
Utm Medium       → utm_medium
Кількість переходів              → clicks
Кількість ассоційованих бронювань → conversions
Сума заброньованих товарів        → conversion_value

UTM BigQuery Schema (tabletki_utm)

Поле Тип Опис
date_from DATE (REQUIRED) Початок звітного періоду
date_to DATE (REQUIRED) Кінець звітного періоду
utm_campaign STRING (REQUIRED) Campaign name або ID
utm_source STRING fb, google, tiktok, dv360, delta...
utm_medium STRING paid, reach, pmax, sku...
clicks INT64 Кількість переходів
conversions INT64 Асоційовані бронювання
conversion_value FLOAT64 Сума заброньованих товарів (грн)
ingested_at TIMESTAMP Час завантаження
source_file STRING api / filename

Upsert логіка

Обидва лоадери автоматично видаляють старі записи за той самий date_from + date_to перед вставкою нових. Тому повторний запуск безпечний.


6. BigQuery Views (Looker Studio)

4 views створено в ad-analytics-hub.tabletki:

View Опис
v_delta_sales_daily Усі продажі Delta Medical, всі типи періодів
v_delta_sales_weekly Агреговані тижневі продажі (GROUP BY)
v_delta_sales_trend Тижневий тренд з market share %
v_market_share Частка ринку по категоріях

Фільтр: manufacturer LIKE '%Дельта Медікел%'

SQL для створення views — у файлі looker_studio_views.sql.


7. Команди перевірки (CLI)

Перевірка через bq CLI

# Кількість записів
bq query --use_legacy_sql=false \
  'SELECT COUNT(*) as total_rows, MIN(date_from) as min_date, MAX(date_to) as max_date FROM `ad-analytics-hub.tabletki.tabletki_sales`'

# Останні завантаження
bq query --use_legacy_sql=false \
  'SELECT date_from, date_to, period_type, COUNT(*) as rows, MAX(ingested_at) as last_ingested FROM `ad-analytics-hub.tabletki.tabletki_sales` GROUP BY 1,2,3 ORDER BY date_to DESC LIMIT 10'

# Продажі Delta Medical за останній тиждень
bq query --use_legacy_sql=false \
  'SELECT product_name, units_sold, revenue_uah, ROUND(pct_category_revenue*100,2) as market_share_pct FROM `ad-analytics-hub.tabletki.v_delta_sales_trend` ORDER BY revenue_uah DESC LIMIT 10'

# Перевірка views
bq query --use_legacy_sql=false \
  'SELECT COUNT(*) FROM `ad-analytics-hub.tabletki.v_delta_sales_daily`'

# UTM — кількість записів
bq query --use_legacy_sql=false \
  'SELECT COUNT(*) as total_rows, MIN(date_from) as min_date, MAX(date_to) as max_date FROM `ad-analytics-hub.tabletki.tabletki_utm`'

# UTM — топ кампаній по кліках
bq query --use_legacy_sql=false \
  'SELECT utm_campaign, utm_source, utm_medium, clicks, conversions, conversion_value FROM `ad-analytics-hub.tabletki.tabletki_utm` ORDER BY clicks DESC LIMIT 10'

Перевірка через API (curl)

# Тест API — отримати список звітів
curl -s -H "Authorization: Bearer $TABLETKI_TOKEN" \
  https://cab-producer.tabletki.ua/api/Reports | jq '.[].Name'

# Тест API — отримати дані за один день
curl -s -X POST \
  "https://cab-producer.tabletki.ua/api/ReportExecution/report?reportType=JSON&reportId=4ed497e3-2e47-11ef-9209-000c29baf0b7" \
  -H "Authorization: Bearer $TABLETKI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"dateFrom":"2026-04-28","dateTo":"2026-04-28"}' | jq 'length'

# Тест API — UTM звіт
curl -s -X POST \
  "https://cab-producer.tabletki.ua/api/ReportExecution/report?reportType=JSON&reportId=72c243dc-7f5a-11f0-9225-000c29baf0b7" \
  -H "Authorization: Bearer $TABLETKI_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"dateFrom":"2026-04-23","dateTo":"2026-04-29"}' | jq 'length'

8. Troubleshooting

Проблема Рішення
401 Unauthorized від API Токен прострочений → оновити на cab-producer.tabletki.ua → API інтеграції
Access Denied в BigQuery Використовуй акаунт master.digital.dm@gmail.com або service account з ролями Data Editor + Job User
Provided Schema does not match При upload в BQ — зняти "Auto-detect schema", використовувати існуючу schema таблиці
Порожня відповідь API Перевір діапазон дат (max -31 день offset, historical max -24 місяці)
ECONNREFUSED VPN може бути потрібен для cab-producer.tabletki.ua

9. Дата обмеження API


10. Контакти