Строим произвольные воронки на событиях в dataStudio
Очень часто, стандартных средств Google Analytics по воронкам, не хватает для необходимого визуального отображения движения пользователей по сайту.
А такие данные часто важны при различных тестах, да и вообще, понимания как ведет себя аудитория.
Что можно делать сейчас?
Если мы говорим про Google Analytics, из существующих методов есть funnel visualization:
довольно старый инструмент, который в бесплатной версии Google Analytics, можно строить только на просмотрах страниц, и если мы хотим использовать события для воронок, то приходится создавать виртуальные страницы, дублирующие события. Кроме того, этот инструмент только показывает общее количество сессий, без возможности какой-либо сегментации, не считая выбора дат.


Также, есть функционал расширенной электронной торговли, в котором, нам никто не мешает передавать свои значения в нужные столбики:
А особенно отчет checkout behaviour, в котором мы можем добавлять до 7 шагов. Проблема в том, что если настроена стандартная воронка, то со второй воронкой будет работать не очень удобно, кроме того, в один момент времени можно смотреть только один сегмент.

Используем DataStudio
DataStudio — простой инструмент для решения задач по визуализации данных, и главное в этом высказывании — простой, не смотря на то, что команда, которая работает над этим инструментом постоянно добавляет новый функционал, по сравнению с другими системами, такими как powerBi, количество возможностей у DataStudio сильно ограничено. Тем не менее, порог входа в использовании этого инструмента крайне низкий, и мы возьмем его для решении нашей задачи.


В DataStudio есть BarCharts, которые, если развернуть, будут похожи на воронки:
Где, в виде dimensions можно передавать event action, а в metrics — unique events. Если просто настроить события по факту загрузки каждого шага, возникает три проблемы:

— если пользователь уйдет с воронки, в рамках сессии, а затем вернется на следующий шаг, то его действие будет записано, то есть нет возможности, как в funnel visualization, поставить галочку "Required?". И не видно, куда именно пользователь отвалился с воронки.

— одна из особенностей dataStudio заключается в том, что мы не можем делать метрики на основе условий, те посчитать сколько пользователь попало в нужную нам воронку в отношении ко всем и сколько успешно дошло до конца, в отношении к тем кто зашел. Можно, конечно же, сделать цели, но слотов для целей не много, и если таких воронок будет много, то их не хватит.

— если воронок несколько, и, особенно их шаги пересекаются, то ничего не выйдет. Например, у нас есть воронки: main - category - product - cart - thankyou и category - product - cart - thankyou, то даже стандартными средствами их не разделить, вторая будет включена в первую.


Метрики в calculated fields с фильтрами
Во-первых, решим проблему с расчетом показателей на базе событий, то есть создадим метрики в DataStudio: какое количество вхождений в воронку и успешных достижений воронки.


Для этого, нам необходимо создать новый custom dimension с scope = session, назовем его sessionID, в GTM создадим новую переменную, типа custom javascript, и напишем туда следующее:
function() {
var now = new Date();
return String(now.getTime()) + '.' + String(Math.round(Math.random()*10000000))
}
Эта переменная генерирует случайный идентификатор, который мы используем как идентификатор сессии. Он нужен нам для корректного расчета метрик в DataStudio.


Затем, необходимо создать новую custom dimension в Google Analytics с scope sessions и запомнить ее индекс:
Но, если мы оставим как есть, то при каждом новом событии tag manager переменная будет генерироваться заново, а нам нужно, чтобы она не изменялась во время всей сессии, поэтому создадим custom js тэг, в которой напишем следующее:
<script>
//30 min cookie  
function setCookie(cname, cvalue) {
    var d = new Date();
    d.setTime(d.getTime() + (30*60*1000));
    var expires = "expires="+ d.toUTCString();
    document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
  
if ({{session_id_cookie}}) {
  setCookie('sessionID', {{session_id_cookie}});  
} else {
  setCookie('sessionID', {{sessionID}});  
}
  
</script>
Правилом активации, сделаем Dom ready. Этот тэг будет проверять наличие sessionID, и если ее нет, то устанавливать, а если есть, до увеличивать время жизни куки до 30 минут (прямо как в google analytics).


А чтобы читать эту переменную, сделаем еще одну переменную в tag manager, типа 1st Party Cookie:
И передадим это все в google analytics:
Как только соберутся данные, в DataStudio мы можем создавать calculated fields, используя dimensions:


COUNT_DISTINCT(CASE WHEN Event Category = 'funnel_main' THEN SessionID ELSE "" END)


Где, функция COUNT_DISTINCT посчитает количество сессий, которые подходят под условие Event Category = 'funnel_main':
А дальше, мы можем посчитать CR, создав новый calculated fields:


COUNT_DISTINCT(CASE WHEN Event Category = 'funnel_main' And Event Action = '4. thank you page' THEN SessionID ELSE "" END)


Или посчитать, сколько пользователей от общего, попали в воронку (тут тип поля лучше поставить процент):


main funnel users / sessions


Передаем данные о прохождении воронок с помощью событий
Так как мы хотим посмотреть сразу несколько воронок, то нам нужны правила того, как пользователь попадает в воронку и как уходит из нее. Логика будет простая:

— если первое посещение сайта главная или категорийная или продуктовая страница, то передаем название воронки и шаг 1:

dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_main', 'eventAction': '1. main page', 'eventLabel': ''})

Передаем, с помощью autoEvent (подробнее тут)

— если вторая или следующая страница, то смотрим название текущей воронки, смотрим предыдущий шаг и также вызываем autoEvent

— если пользователь уходит с воронки, то также вызываем соответствующее событие с информацией откуда ушел (с воронки какого типа и с какого шага)


Общий код будет выглядеть так:

<script>
  
//30 min cookie  
function setCookie(cname, cvalue) {
    var d = new Date();
    d.setTime(d.getTime() + (30*60*1000));
    var expires = "expires="+ d.toUTCString();
    document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
  
if ({{session_id_cookie}}) {
  setCookie('sessionID', {{session_id_cookie}});  
} else {
  setCookie('sessionID', {{session_id}});  
}
  
  
  
//if first pageview  
if (!{{start_session}}) {
  	//first step for main funnel
	if ({{Page Path}} == '/') {
		dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_main', 'eventAction': '1. main page', 'eventLabel': ''})
      	setCookie('funnel_type', 'main');
     	setCookie('previous_page', 'main');
  	}
  	//first step for category or search funnel
  	if ({{pageType}} == 'Category' || {{Page Path}} == '/search/new') {
		dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_cat_search', 'eventAction': '1. cat or search page', 'eventLabel': ''})
       	setCookie('funnel_type', 'category/search');
     	setCookie('previous_page', 'category/search');
      
    }
  	//first step for product funnel
  	if ({{pageType}} == 'Product') {
		dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_product', 'eventAction': '1. product page', 'eventLabel': ''})
      	setCookie('funnel_type', 'product');
     	setCookie('previous_page', 'product');
    }
  
    
	setCookie('start_session', 1);
    
//if second or more pageviews      
} else {
  	//second step for main funnel
  	if ({{pageType}} == 'Category' || {{Page Path}} == '/search/new') {
		if ({{funnel_type}} == 'main' && {{previous_page}} == 'main') {
			dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_main', 'eventAction': '2. category page', 'eventLabel': ''})
	     	setCookie('previous_page', 'category/search');          
        }
    }
  	if ({{pageType}} == 'Product') {
		if ({{funnel_type}} == 'main' && {{previous_page}} == 'category/search') {
			dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_main', 'eventAction': '3. product page', 'eventLabel': ''})
	     	setCookie('previous_page', 'product');          
          
        }
		if ({{funnel_type}} == 'category/search' && {{previous_page}} == 'category/search') {
			dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_cat_search', 'eventAction': '2. product page', 'eventLabel': ''})
	     	setCookie('previous_page', 'product');          
        }
      
    }
  	if ({{Page Path}} == '/moyobasket/basket.html' && {{previous_page}} == 'product') {
		if ({{funnel_type}} == 'main') {
			dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_main', 'eventAction': '4. cart page', 'eventLabel': ''})
	     	setCookie('previous_page', 'cart');          
        }
		if ({{funnel_type}} == 'category/search' && {{previous_page}} == 'product') {
			dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_cat_search', 'eventAction': '3. cart page', 'eventLabel': ''})
	     	setCookie('previous_page', 'cart');          
          
        }
		if ({{funnel_type}} == 'product' && {{previous_page}} == 'product') {
			dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_product', 'eventAction': '2. cart page', 'eventLabel': ''})
	     	setCookie('previous_page', 'cart');          
        }
      
    }
  	if ({{Page Path}} == '/moyobasket/proceed.html') {
		if ({{funnel_type}} == 'main' && {{previous_page}} == 'cart') {
			dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_main', 'eventAction': '5. checkout page', 'eventLabel': ''})
	     	setCookie('previous_page', 'checkout');          
          
        }
		if ({{funnel_type}} == 'category/search' && {{previous_page}} == 'cart') {
			dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_cat_search', 'eventAction': '4. checkout page', 'eventLabel': ''})
	     	setCookie('previous_page', 'checkout');          
          
        }
		if ({{funnel_type}} == 'product' && {{previous_page}} == 'cart') {
			dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_product', 'eventAction': '3. checkout page', 'eventLabel': ''})
	     	setCookie('previous_page', 'checkout');          
        }
    
    }
  	if ({{pageType}} == 'ThankYouPage') {
		if ({{funnel_type}} == 'main' && {{previous_page}} == 'checkout') {
			dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_main', 'eventAction': '6. thank you page', 'eventLabel': ''})
        }
		if ({{funnel_type}} == 'category/search' && {{previous_page}} == 'checkout') {
			dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_cat_search', 'eventAction': '5. thank you page', 'eventLabel': ''})
        }
		if ({{funnel_type}} == 'product' && {{previous_page}} == 'checkout') {
			dataLayer.push({'event': 'autoEvent', 'eventCategory': 'funnel_product', 'eventAction': '4. thank you page', 'eventLabel': ''})
        }
    
    }  
  	//if user exits from funnel
  	if ({{pageType}} != 'ThankYouPage' && {{Page Path}} != '/moyobasket/proceed.html' && {{Page Path}} != '/moyobasket/basket.html' &&{{pageType}} != 'Product' && {{pageType}} != 'Category' && {{Page Path}} != '/search/new' && {{previous_page}} != 'other') {
	  dataLayer.push({'event': 'autoEvent', 'eventCategory': 'exitfunnel_'+{{funnel_type}}, 'eventAction': {{Page Path}}, 'eventLabel': {{previous_page}}})  
      
    	setCookie('previous_page', 'other');  
    }
        
    //increment, count of pages    
  	setCookie('start_session', parseInt({{start_session}}) + 1);
    
}
  
  
</script>
После чего в dataStudio делаем BarCharts, переворачиваем его, и ставим в dimensions EventAction, а в metrics — unique events. И устанавливаем фильтр соответствующей воронки:
Также, элементом filter control, выставляем фильтры по типу устройств и трафика.
Made on
Tilda