Конверсія х2: як ми апгрейднули платформу для навчання JS

Всім привіт! Мене звати Олександра, і я QA Engineer в EdTech-компанії Mate academy. Хоча моя основна діяльність полягає у тестуванні нашого продукту, робота в стартапі надає можливість бути залученою у різних напрямах.

Одного дня ми поставили перед собою задачу збільшити конверсію в x2 під час проходження базового курсу JavaScript на платформі. І нам вдалось.

У цьому блозі я поділюся досвідом, що саме ми зробили, аби пофіксити «слабкі місця». Сподіваюсь, текст буде корисний не тільки для edtech-компаній, які також сфокусовані на навчанні, а й загалом для технічних спеціалістів, які формують технічні навчальні матеріали.

Контекст, і що було не зовсім так

Для розуміння контексту, декілька слів про сам курс. Це базовий безкоштовний курс для вивчення основ JavaScript для тих, хто ще не знайомий з програмуванням. Як FreeCodeCamp, де доступ до онлайн-платформи відкритий кожному охочому. Навчання складається з відеолекцій, теоретичних матеріалів та практичних завдань (написання коду).

Проаналізувавши статистику проходження курсу, ми виявили, що лише 8,61% користувачів доходило до кінця. Тобто для багатьох він ставав не таким і базовим, як нам здавалось.

Щоб зрозуміти, де саме в курсі маємо прогалини, використовували статистичні дані з Amplitude. Зокрема:

  • конверсія від теми до теми (скільки % від попереднього топіку проходять наступний топік);
  • графік з щотижневою конверсією (для трекання загального результату змін);
  • графік з найбільш дизлайкнутими задачами;
  • графік із задачами з найбільшою кількістю перевірок (велика кількість перевірок — це нормально для складних задач, але якщо задача відносно проста, а перевірок багато — варто задуматись над причиною).

Скриншот з Amplitude зі статистикою, скільки разів запускали код для перевірки певної задачі. На графіку — топ-12 задач з найбільшою кількістю запусків коду

Крім того, студенти можуть надіслати фідбек на матеріали курсу через форму «Повідомити про помилку», тому ще одним джерелом інформації був безпосередньо зворотний зв’язок студентів до задач.

Опрацювавши вхідну інформацію, ми висунули гіпотези і пріоритезували наступні активності:

  • рефакторинг умов,
  • додавання підказок,
  • розділення складної задачі на 2+ простіші,
  • додавання простих задачок перед складними та
  • інтеграція квізів.

Рефакторинг умов

Як-то кажуть, без чіткого тз — результат хз. Тому ми почали з визначення умови завдання. Саме завдання може бути дуже простим, але якщо студент не зрозуміє, що від нього вимагається, це значно ускладнить подальший процес.

До рефакторингу умови більшість задач формувались у довільній формі. Часто на початку була якась довга передісторія, потім загальний опис задачі: функція, яку треба реалізувати, параметр, який вона приймає, трохи про те, що має робити функція і, якщо пощастить — ще й тип даних, який функція має повернути. Десь були приклади вхідних та вихідних даних, десь не було.

Проаналізувавши умови задач, до яких ми отримували найбільше фідбеків по типу «не розумію, що від мене хочуть!», ми дійшли висновку, що саме ускладнює розуміння задач:

  • Довга умова. Якщо це займає більшу частину задачі — з масиву тексту студентам важко виокремити, яка ж задача перед ними стоїть. Так, так, навіть якщо там «дуже цікава» історія про роботів, які вчаться сортувати коробки.
  • Відсутність конкретики. Треба оголосити функцію, яка приймає якийсь параметр і повертає результат... А як має називатися функція? А який тип даних приймає? А який тип даних повертає? Не в усіх задачах ця інформація була чітко вказана, а це важливо. Умовно, якщо тести очікують рядок, а повертається масив — тести проваляться, і якщо інформація щодо типу даних не була вказана в умові, це може заплутати студента.
  • Відсутність прикладів. Текстовий опис — це чудово, але конкретний приклад ефективніше тисячі слів. Просто функція, вхідні дані і вихідні дані: що може бути краще?

Як виправити вищезгадані проблеми? Розробіть універсальну структуру для опису задачі і дотримуйтесь її. Що ми і зробили. Тепер наша формула «ідеального опису задачі» складається із наступних складників:

  • Коротенька передісторія (за бажанням).
  • Назва функції (методу).
  • Назви та типи даних вхідних параметрів.
  • Тип вихідних даних.
  • Інструкції: що саме має робити функція (метод).
  • Примітки (якщо потрібно: тут може бути, наприклад, інструкція щодо якихось edge cases).
  • Приклади.

Як наша формула виглядає на практиці

Розглянемо задачу «Remove vowels» з теми «Working with strings».

Ось як виглядала умова цієї задачі до рефакторингу:

Які проблеми є в такому описі:

  • сам текст задачі написаний одним абзацем, більша частина — «не в тему» (історія про боса і його напружені стосунки з голосними, заклик до «досвідченого програміста» виправити це);
  • не вказано, який тип даних повернути: судячи з опису і прикладів, це має бути рядок, але краще мати чітку вказівку;
  • не дуже зрозуміло, що мається на увазі під голосними. Чи вважається, наприклад, «y» голосною? Чи має функція видаляти як великі, так і малі літери? Другий приклад вказує, що «y» таки вважається голосною, а видаляти треба тільки малі літери, але в описі це прямо не вказано.

Застосувавши нашу формулу «ідеального опису задачі», ми переписали умову, і тепер вона виглядає ось так:

Що маємо у цьому випадку:

  • коротенька передісторія про боса, який не любить голосні літери;
  • назва функції (removeVowels), назва та тип вхідних даних (рядок doc), тип вихідних даних (рядок);
  • інструкція: голосні мають бути видалені;
  • примітка — які саме літери і в якому регістрі треба видалити;
  • приклади: функція, вхідні дані (наприклад, ’document’) і результат, який вона повертає відповідно до цих даних (’dcmnt’).

Ось і все! Менше тексту, більше конкретики — і умова до задачі готова! Але це ще не вирішує усе...

Підказки

Ще одна поширена проблема: студент розуміє, що від нього вимагається у задачі, але не знає, як саме це реалізувати. В такому випадку було б непогано давати якусь підказку щодо алгоритму дій, який сприятиме виконанню задачі.

Але якщо розміщувати таку підказку прямо в умові задачі, виникають дві проблеми. По-перше, це робить умову надто довгою, що суперечить нашому попередньому правилу про стислість і конкретику. По-друге, не всім студентам потрібні підказки. Деяким, наприклад, не подобається, що є розписаний алгоритм, і куди цікавіше дійти до рішення самостійно.

Щоб у студента був доступ до підказки, але при цьому вона не відкривалась одразу і не перевантажувала умову задачі, ми заховали її під spoiler button.

Як це виглядає? Скажімо, у нас є ось така задача із теми «Arrays»:

По дефолту підказка закрита. Тому якщо студент прагне вирішити задачу самостійно, у нього є така змога. Але якщо студент відчуває, що застряг — можна відкрити підказку і глянути алгоритм дій або натяк, як вирішити цю задачу:

Крім того, студенти часто допускають схожі помилки, як-от: не закривають якусь фігурну дужку, пишуть десяткові числа через кому, а не через крапку, або ж створюють нескінченний цикл. У результатах запуску коду є інформація про такі помилки, але на початкових етапах студентам важко зрозуміти, що ж пішло не так і як це виправити. Тому такі типові помилки зручно виносити в підказки, щоб студенти швидше розблоковували себе й рухалися далі.

Наприклад, у нас є задача з десятковими числами, які студенти часто пишуть через кому, про що їм сигналізує помилка «Octal literals are not allowed in strict mode». Оскільки з її тексту не дуже очевидно, що саме пішло не так, це винесено в підказку до завдання:

Або ж задачі з циклами. Часто саме там студенти забувають про крок циклу або прописують неправильні умови виходу з нього. Код виконується 5 секунд і після цього зʼявляється страхітливе повідомлення «The execution time limit has been reached. Task timed out after 5.05 seconds». Щоб студенти не переживали, що це за 5 секунд і чому їх task timed out, ми додали підказку щодо цієї помилки:

Розділення складної задачі на 2+ простіших

Конкретизація умов і підказки можуть спростити розуміння та виконання задач. Але є і такі завдання, що вже не скоротиш, проте студентам все ж важко з ними розібратися. Що ж робити в подібній ситуації?

Такі задачі доцільно розділяти на дві або більше простіших: тоді й умови будуть коротші, й завдання конкретніші.

Наприклад: на одній з перших тем нашого курсу drop-off студентів з попереднього кроку (початку вивчення цієї теми) був 43% — а це всього лиш Main concepts, тобто базові поняття з JavaScript.

Потрібно було зрозуміти, чому студенти відвалюються навіть на таких простих, здавалося, б задачах. Так, в цій темі була задача, де потрібно закоментувати код (частину — однорядковим коментарем, частину — багаторядковим), а також розкоментувати один рядок. Ось як виглядала умова та файл з кодом для завдання:

Здавалося б, жодних складних алгоритмів, але користувачам не дуже це подобалось. Однак скорочувати умову вже нікуди, підказками особливо не допоможеш, а дати готовий розвʼязок — не варіант.

Тому ми розділили цю задачу на дві окремих: одну — із розкоментовуванням коду, іншу — із закоментовуванням (лише однорядковим коментарем). Частину з багаторядковим коментарем вилучили, бо на початкових етапах без цього можна обійтись. Тепер у кожній задачі вимагається лише одна конкретна дія:




Такий розділ задачі на дві простіші, а також спрощення умов інших задач допомогли нам знизити drop-off студентів з цієї теми майже вдвічі — з 43% до 21,9%.




Додавання простих задачок перед складними

Ми скоротили умови, додали підказки, де це потрібно, і розділити деякі задачі на декілька простіших. Але що робити, якщо є складна задача, яку неможливо розділити на легші, проте вона корисна і її треба залишити в програмі? У нас були такі ситуації з кількома темами: спочатку йде проста задача, а потім відразу щось складне, без попередньої підготовки. Щось типу спочатку скласти 2+2, а потім відразу приклад на декілька різних математичних дій, а то й квадратне рівняння. Статистика підказувала, що на таких завданнях багато студентів переставали продовжувати.

Владнали ми це наступним чином. Щоб плавно підводити студентів до розв’язання складних задач, ми додали перед ними простіші. Особливо актуальним це виявилося для таких тем, як робота з циклами, рядками та масивами.

Приміром у циклах ми затрекали, що першою задачею було дописати умову виходу і крок циклу, що виводить в консоль числа від 1 до N. Це неважко, але вже в наступній задачі необхідно підрахувати суму чисел від 1 до N за допомогою циклу. А після цієї — зробити те саме, але вже в циклі з певним кроком. Студенти були настільки не в захваті від різкого підвищення складності, що ці задачі були одними з найбільш дизлайкнутих. Тож ми додали ще три задачі на цикли і трохи змінили їх послідовність.

Зараз завдання в темі у такому порядку:

  1. Виправити нескінченний цикл, в якому ніколи не виконується умова виходу (а це часта помилка серед студентів).
  2. Дописати умову зупинки циклу, що виводить в консоль числа від 1 до N.
  3. Дописати цикл, що виводить в консоль числа від 1 до N з кроком step (тут вже треба дописати початкове значення, умову зупинки та крок циклу).
  4. Створити цикл, який виводить числа від N до 1, тобто у зворотному порядку.
  5. Створити функцію, яка підраховує суму чисел від 1 до N.
  6. Створити функцію, яка підраховує суму чисел від 1 до N з кроком step.
  7. Додаткова задача на підрахунку прибутку від банківського депозиту під заданий відсоток на певний період.

Тепер студенти мають на початку простіші задачі, що логічно підводять їх до складніших. Це дає свої результати: drop-off студентів на цій темі знизився на 28% (з 15,4% до 11,1%).




Квізи

Що ж, з задачами на написання коду розібралися. Оновлені, вони мають стислі та конкретні умови з прикладами; підказки; за необхідності розділені на дві чи більше менші задачі; де необхідно — додані простіші задачі, що передують складнішим. Але і в найпростіших задачах виникає ситуація, коли студенти пишуть код навмання за принципом «А раптом вийде?/ А якщо запустити той самий код 5 разів, може, з пʼятої спроби він нарешті спрацює?».

Щоб перевірити розуміння студентами теорії і логіку їхніх дій, ми створили невеликі квізи (5-10 питань) до майже усіх тем курсу. Ці квізи можна пройти стільки разів, скільки потрібно, але зараховуються вони при мінімум 80% правильних відповідей.

Більшість питань у квізах повʼязані з кодом. Наприклад, що виведе ось такий код, вибери код, який робить ось таку дію, яке значення матиме ось ця змінна після виконання ось цього коду. Це дозволяє студентам вчитись аналізувати код і його роботу перед тим, як безпосередньо почати його писати.

Але оскільки квіз можна перепройти декілька разів, студенти можуть просто запамʼятати правильні відповіді, так і не розуміючи логіки. Щоб студенти не просто клацали відповіді, а й розуміли, чому саме цей варіант правильний, а інші — ні, ми додали пояснення. Як тільки студент відповів на запитання і перевірив його — правильна відповідь підсвічується зеленим, неправильна (якщо студент її вибрав) — червоним, а під питанням зʼявляється пояснення щодо правильної відповіді.

Наприклад, ось так виглядає питання з квіза до теми «Boolean»:

А так виглядатиме це питання після того, як студент відповів на нього і перевірив свою відповідь (у цьому випадку — неправильну):

А тепер резюмуємо

Щоб побачити, як все вищесказане вплинуло на конверсію курсу з JavaScript Basics, розгляньмо графік з Amplitude:

Графік показує, скільки користувачів, що починають проходити курс JavaScript Basics, проходять його до кінця:

  • з 23 липня до 21 жовтня 2021 8,61% юзерів (324 з 3765) пройшли курс до кінця;
  • з 1 серпня до 30 жовтня 2022 17,8% юзерів (1694 з 9503) пройшли курс до кінця.

Так, конверсія проходження курсу зросла у більше ніж 2 рази (з 8,61% до 17,8%), а отже після апгрейду вдвічі більше студентів завершують його. Це дозволяє вдвічі зменшити бюджет на маркетинг для цього напрямку і заощадити кошти компанії. Умовно, якщо в місяць на маркетинг зазвичай витрачалось $10k, то це $60k економії в рік.

Але це не означає, що ми більше не працюємо з наповненням. Досконалості немає меж, так що робота з прокачкою курсу постійно триває. Ми продовжуємо моніторити фідбеки від студентів, графіки конверсії від модуля до модуля та статистику дизлайків, і вносимо відповідні зміни.

І декілька рекомендацій

Аналізуючи це все, ми вивели певні рекомендації, які можуть стати у пригоді тим, хто працює над навчальними програмами:

  • Створюйте стислі і конкретні описи завдань: найкраще — розробіть чітку структуру і дотримуйтесь її. Все має бути послідовно.
  • Аналізуйте, з якими проблемами студенти стикаються найчастіше, і додайте підказки, що допоможуть їх вирішити. Це особливо актуально на початкових етапах, коли користувачам ще важко зрозуміти, що саме пішло не так, і як це виправити.
  • Розбийте великі завдання на декілька менших, щоб користувачеві було легше «їсти слона частинами».
  • Переконайтеся, що завдання мають інкрементальну складність, і користувач поступово рухається від легших до важчих тасків, без різких «перепадів» складності.
  • Додавайте завдання на повторення матеріалів, щоб студенти закріпили свої знання теорії безпосередньо перед практикою.
  • Збирайте статистику і фідбеки: що в курсі найбільше або найменше подобається студентам, чому так, які завдання даються легко, а які — навпаки. Опрацьовуйте цю інформацію і продовжуйте вдосконалювати свої програми, адже це — нескінченний процес!

Сподобалась стаття? Натискай «Подобається» внизу. Це допоможе автору виграти подарунок у програмі #ПишуНаDOU

👍ПодобаєтьсяСподобалось24
До обраногоВ обраному5
LinkedIn
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Дозволені теги: blockquote, a, pre, code, ul, ol, li, b, i, del.
Ctrl + Enter
Це базовий безкоштовний курс для вивчення основ JavaScript для тих, хто ще не знайомий з програмуванням.

А де ж посилання на нього?

У процесі модерації лінк прибрали. Але дякую, що запитали. Базовий курс по JS викладається у межах курсу Frontend. Щоб зайти на базовий курс — необхідно лише авторизуватись. Залишаю посилання: mate.academy/courses/frontend

Підписатись на коментарі