ODP + CMS

  • Updated

Integrate Optimizely Content Management System (CMS) with Optimizely Data Platform (ODP) to:

  • Track how your site visitors interact with your web content, including articles, videos, and forms, to understand what parts of your site they engage with, how frequently, and what topics they are interested in.
  • Use ODP’s powerful and flexible segmentation engine to segment your visitors based on their interactions with your content and create reports to understand and share your content's performance across your organization.
  • Use insights gained from your CMS integration to inform your content strategy. Make data-driven decisions about what topics your visitors find the most engaging and their preferred content types.

Prerequisites

You must have the ODP JavaScript tag added to your site, which tracks visitor page view events.

Configure the integration

  1. In ODP, go to the App Directory.
  2. Select the Optimizely CMS app.
  3. Click Install App.
    install CMS app into ODP

Track additional events

You can insert additional code snippets in the ODP JavaScript tag on your site to capture additional events, including form fills, searches, and video watches. See the following examples.

Forms

if (typeof $$epiforms !== 'undefined') { 
    $$epiforms(document).ready(function myfunction() { 
	    $$epiforms(".EPiServerForms").on("formsNavigationNextStep formsNavigationPrevStep formsSetupCompleted 
		formsReset formsStartSubmitting formsSubmitted formsSubmittedError formsNavigateToStep 
		formsStepValidating", 
    function (event, param1, param2) { 
	    var eventType = event.type; 
	    var formName = event.workingFormInfo.Name; 
	    if (eventType == 'formsSetupCompleted') { 
		    console.log('ODP: web_form impression: ' + formName); 
		    zaius.event('web_form', { action: 'impression', form_name: formName }); 
		} else  if (eventType == 'formsStepValidating') { 
		    if (!event.isValid) { 
			    console.log('ODP: web_form validation failed: ' + formName); 
			    zaius.event('web_form', { action: 'submission_validation_failed',
				 form_name: formName }); } 
		} else  if (eventType == 'formsSubmitted') { 
			console.log('ODP: web_form submission: ' + formName); 
		    zaius.event('web_form', { action: 'submission', form_name: formName }); 
		} else { 
			// handle other form events here 
		} 
		}); 
	}); 
}

Search events

$(document).keypress(function(event){ 
    var key = event.which; 
    if(key == 13) // the enter key code 
    { 
	    var searchValue = null; 	
	    var searchInputs = $('.jsSearchText'); 
	    if (searchInputs != null) 
	    { 
		    for (var i = 0; i < searchInputs.length; i++) 
		    { 
			    var input = searchInputs[i]; 
			    if (input.value != null && input.value != '') 
			    { 
				    searchValue = input.value; 
				    console.log('ODP: search: ' + searchValue); 
				    zaius.event('navigation', { action: 'search', search_term: searchValue }); 
				} 
			} 
		} 
	} 
});

The following script tracks searches that have no results as well as search result click events.

$(document).ready(function() { 
    var searchValue = null; 
	const params = new URLSearchParams(window.location.search); 
	searchValue = params.get('search'); 
	if (document.querySelector('.content-search-results') == null 
	&& document.querySelector('.product-tile-grid') == null) 
	{ 
		console.log("ODP: Track no search results") 
		zaius.event('search', { action: 'no_results' , search_term: searchValue }); 
		} 
	$('.content-search-results > a').click(function() { 
		let clickedLink = $(this).attr("href"); 
		console.log("ODP: Track search result link click -- " + clickedLink + 
		" (search term: " + searchValue + ")"); ,
		zaius.event('search', { action: 'click' , search_term: searchValue, 
		search_clicked_content: clickedLink }); 
	}); 
	$('.product-tile-grid').click(function() { 
		let site = location.protocol + '//' + location.host; 
		let clickedProd = $(this).children('.product-tile-grid__title').children('a').attr("href"); 
		let clickedProdLink = site + clickedProd; 
		console.log("ODP: Track search result product click -- " + clickedProdLink + 
		" (search term: " + searchValue + ")"); 
		zaius.event('search', { action: 'click' , search_term: searchValue, 
		search_clicked_product: clickedProdLink }); 
	}); 
});

Video events

To begin tracking video events, first create the following custom fields:

  • video_id_yt – Text (YouTube video ID)

  • video_play_percentage – Number

  • video_title – Text

The following script tracks YouTube video events, including video loads, video plays, video progress (10%, 25%, 50%, 75%, 90%, and completed), and pauses/restarts. It leverages the YouTube API for iframe embeds.

This script only tracks if there is a single YouTube video block on the page because it targets the video based on the ID youtube-block attribute when the block renders.
var tag = document.createElement('script'); 
tag.id = 'youtube-iframe'; 
tag.src = 'https://www.youtube.com/iframe_api'; 
var firstScriptTag = document.getElementsByTagName('script')[0]; 
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag); 
var player; 
function onYouTubeIframeAPIReady() { 
    player = new YT.Player('youtube-block', { 
	    events: { 
		    'onReady': onPlayerReady, 
		    'onStateChange': onPlayerStateChange 
		    }
	}); 
} 
var sendEvents = true; 
var videoDuration; 
var videoId; var videoTitle; 
var timer; 
var currentProgress = 0; 
var previousProgress = 0; 
var progressEventPoints = [10, 25, 50, 75, 90]; 
var startedPlay = false; 
var pausedPlay = false; 
var halfway = false; 
function writeLoadVideoEvent() { 
	console.log("ODP - video loaded - " + videoTitle); 
	if (sendEvents) { 
		zaius.event("video", { 
			action: "loaded", 
			video_id_yt: videoId, 
			video_title: videoTitle, 
			video_play_percentage: 0, 
			video_action: true 
			}); 
		} 
	} 
function writeStartVideoEvent() { 
	console.log("ODP - video started"); 
	if (sendEvents) { 
		zaius.event("video", { 
			action: "started", 
			video_id_yt: videoId, 
			video_title: videoTitle, 
			video_play_percentage: 0, 
			video_action: true 
			}); 
		} 
} 
function writeHalfVideoEvent() { 
	console.log("ODP - video 50% completed"); 
	if (sendEvents) { 
		zaius.event("video", { 
			action: "watched_half", 
			video_id_yt: videoId, 
			video_title: videoTitle, 
			video_play_percentage: 50, 
			video_action: true 
			}); 
		} 
	} 
function writeEndVideoEvent() { 
	console.log("ODP - video completed"); 
	if (sendEvents) { 
		zaius.event("video", { 
			action: "watched", 
			video_id_yt: videoId, 
			video_title: videoTitle, 
			video_play_percentage: 100, 
			video_action: true 
		}); 
	} 
} 
function writeVideoProgressEvent(percent) { 
	console.log("ODP - video " + percent + "% completed"); 
	if (sendEvents) { 
		zaius.event("video", { 
			action: "video_progress", 
			video_id_yt: videoId, 
			video_title: videoTitle, 
			video_play_percentage: percent, 
			video_action: true 
		}); 
	} 
} 
function writePauseVideoEvent(percent) { 
	console.log("ODP - video paused " + percent + "%"); 
	if (sendEvents) { 
		zaius.event("video", { 
			action: "paused", 
			video_id_yt: videoId, 
			video_title: videoTitle, 
			video_play_percentage: percent, 
			video_action: true 
		}); 
	} 
} 
function writeRestartVideoEvent(percent) { 
	console.log("ODP - video restarted at " + percent + "%"); 
	if (sendEvents) { 
		zaius.event("video", { 
			action: "restarted", 
			video_id_yt: videoId, 
			video_title: videoTitle, 
			video_play_percentage: percent, 
			video_action: true 
			}); 
		} 
} 
function onPlayerReady(event) { 
	videoDuration = player.getDuration(); 
	videoId = player.getVideoData().video_id; 
	videoTitle = player.getVideoData().title; 
	writeLoadVideoEvent(); 
} 
function play_progress_reached() { 
	current_time = player.getCurrentTime(); 
	currentProgress = parseInt((current_time / videoDuration) * 100); 
	if (player.getPlayerState() == YT.PlayerState.PLAYING) { 
		if (startedPlay == false) { 
			writeStartVideoEvent(); 
			startedPlay = true; 
		} else if (pausedPlay == true) { 
			writeRestartVideoEvent(currentProgress); 
			pausedPlay = false; 
		} else if (currentProgress > 0 && currentProgress % 5 == 0 && 
		currentProgress > previousProgress) 
{ 
		if (currentProgress > previousProgress && progressEventPoints.includes(currentProgress)) { 
			writeVideoProgressEvent(currentProgress); 
			previousProgress = currentProgress; 
		} 
		} 
	} else if (player.getPlayerState() == YT.PlayerState.PAUSED) { 
		writePauseVideoEvent(currentProgress); 
		pausedPlay = true; 
		clearInterval(timer); 
	} else if (player.getPlayerState() == YT.PlayerState.ENDED) { 
		writeEndVideoEvent(); 
		clearInterval(timer); 
	} else { 
		clearInterval(timer); 
		} 
} 
function play_progress_callback() { 
	clearInterval(timer); 
	current_time = player.getCurrentTime(); 
	currentProgress = parseInt((current_time / videoDuration) * 100); 
	remaining_time = videoDuration - current_time; 
	if (remaining_time > 0) { 
		timer = setInterval(play_progress_reached, 500); 
	} 
} 
function onPlayerStateChange(event) { 
	if (event.data == YT.PlayerState.PLAYING) { 
		console.log("Video playing"); 
	} 
	clearInterval(timer); 
	play_progress_callback(); 
}