12 Storeez Retail Quality & CX

Документация

Страница построена на реальных данных 12 STOREEZ. Ниже — источники, правила расчёта и то, что нужно знать, прежде чем принимать по этим цифрам решения.

1. Источники данных

Всё берётся из Google-таблицы «проверки», собирается скриптом node scripts/build_landing_data.js и складывается в data.js. Руками этот файл не правят — правки затрутся следующей сборкой.

ЧтоОткудаОбъём
Дивизионы и магазиныscripts/lib/qa_stores.js — схема управления розницей6 дивизионов, 51 магазин
Проверкивкладка QA_STORE_WEEK2 119 проверок трёх видов
Отзывы и оценкивкладка VoC11 539 строк, из них 2 359 с текстом

Три вида проверок

  • Internal Audit — внутренняя инспекция, 174 проверки.
  • Video Check List — проверка по видеокамерам, 650 проверок.
  • Mystery Shopper — тайный покупатель, 1 295 проверок.

Четвёртая составляющая считается иначе

Доля позитива — это не проверка, а доля: сколько оценок «5» среди всех оценок и обращений клиентов за период. Она хранится недельными корзинами «пятёрки / все оценки», которые складываются, и только потом берётся отношение. Поэтому месяц и год — строгая доля, а не среднее из недельных процентов.

Доля показывается только при 5 и более оценках за период. Ниже этого порога она скачет на одном отзыве: медиана — 7 оценок на магазин за неделю, и при пороге в 3 ровно половина недель давала бы ровные «100%».

2. Как считаются показатели

Service Score

Простое среднее тех составляющих, по которым за выбранный период есть значение. Отсутствующая составляющая не считается нулём и не входит в знаменатель. Если нет ничего — выводится «Нет данных», а не ноль.

Пример: Internal Audit 90, Video Check List 95, Доля позитива 92, Mystery Shopper за период не проводился → (90 + 95 + 92) / 3 = 92,3.

Voice of Customer

На уровнях «Retail» и «Дивизион» проценты позитива и негатива считаются суммой отзывов, а не средним процентов по магазинам. Разница не косметическая: на текущих данных строгая доля позитива по рознице — 56,7%, тогда как наивное среднее по магазинам дало бы 53,9%.

Тональность: оценка «5» — позитив, оценки 1–4 — негатив. Это методика, принятая в проекте. Нейтральной категории в модели нет.

Динамика

Дельта — разница с предыдущим аналогичным периодом. Знак и стрелка проставлены всегда, цвет нигде не является единственным носителем смысла.

Подсветка проблемных зон

Магазин помечается бордовым при балле ниже 85, падении от 3 пунктов или доле негатива выше 45% при базе от 8 отзывов. Пороги демонстрационные и подлежат согласованию.

3. Обезличивание цитат

Страница размещена на внешнем сервере, поэтому тексты отзывов проходят обезличивание на этапе сборки. В исходной таблице ничего не меняется.

  • Имена сотрудников рядом с должностью, после «зовут», «по имени» и слов благодарности → [имя]
  • Телефоны → [телефон], адреса почты → [почта]
  • Номера заказов, чеков и карт → [номер]
  • Конкретные даты → [дата]

Обезличено 436 текстов из 2 359, всего 496 замен. Смысл и тональность цитаты сохраняются полностью: маскируется только то, что позволяет опознать человека.

Правило намеренно консервативно в одну сторону: слово маскируется только рядом с маркером (должность, «зовут», благодарность) и с заглавной буквы. Иначе под «имя» попадали обычные слова — «Директор отказалась продать», «консультантов достаточно». Города, названия ТЦ и бренд не трогаются.

4. Ограничения — прочитать до принятия решений

Что осталось за пределами страницы

  • 507 отзывов с текстом не привязаны к магазину и в разрез не попали: 219 из них со Store = «-» (ecom и доставка), остальные — выведенные из отчётности точки (Большая Конюшенная, Атриум, Европолис СПб, Мега Химки Аутлет) и не-магазины.
  • Ecom исключён целиком: 49 проверок без привязки к торговой точке.
  • Оценки без комментария (8 939 строк) в цитаты не идут, но в долю позитива входят.

Свойства данных, которые легко принять за ошибку

  • Mystery Shopper бывает выше 100 — до 103 баллов в 91 проверке. В анкете есть бонусные вопросы. Это свойство первоисточника, значения не обрезаются.
  • Недельный срез тонкий. Camera audit и Internal audit проводятся не каждую неделю, поэтому на недельном уровне у большинства магазинов заполнены одна-две составляющие. Для сравнения магазинов между собой надёжнее месяц или год.
  • Темы отзывов — эвристика. Определяются по ключевым словам, названы по критериям таксономии 12 STOREEZ, но это не официальная классификация из листа «Разметка»: там нет привязки к магазину. Порядок тем показывает акценты, точные числа сверять с «Разметкой».
  • Магазины с малой базой отображаются наравне с крупными: порога достоверности по числу проверок пока нет.

Технические

  • Данные — снимок на дату сборки, не живой поток. Обновление — повторный запуск скрипта.
  • Состояние экрана не отражается в адресной строке: конкретный магазин нельзя переслать ссылкой.
  • Нет экспорта в XLSX и PDF, нет сравнения с аналогичным периодом прошлого года.
5. Архитектура и обновление

Три слоя

  • Данныеdata.js. Четыре плоских массива плюс positivity. Знает про источник, не знает про расчёты и вёрстку.
  • Расчёты — секция CALC в начале app.js: чистые функции без обращений к DOM.
  • Интерфейс — остальная часть app.js. Получает цифры только через aggregate(), сам ничего не вычисляет.

Обновить данные

# обезличенные цитаты (по умолчанию) — этот вариант уходит на сервер
node scripts/build_landing_data.js

# исходные тексты, только для локального просмотра
node scripts/build_landing_data.js --raw-quotes

# совсем без текстов, только агрегаты
node scripts/build_landing_data.js --no-quotes

Перейти на живой источник

Интерфейс обращается к данным ровно один раз — window.DATA_SOURCE.load(). Достаточно вернуть из него объект той же формы:

{ divisions:  [{ id, name }],
  stores:     [{ id, division_id, name, city }],
  checks:     [{ id, store_id, type, date, score }],   // type: audit|video|mystery
  voc_reviews:[{ id, store_id, date, sentiment, topic, text }],
  positivity: [{ store_id, date, five, all }] }        // date = понедельник недели
  • date — строка YYYY-MM-DD; недели, месяцы и годы считаются на клиенте.
  • score — число или null. Отсутствие оценки передавать именно как null, не нулём.
  • sentimentpositive либо negative.
  • app.js и index.html при этом не трогаются.

Источник данных: Google Sheets.