![JAR search and dependency download from the Maven repository](/logo.png)
com.eclipsesource.tabris.tracking.Tracking Maven / Gradle / Ivy
Show all versions of tabris-tracking Show documentation
/*******************************************************************************
* Copyright (c) 2014 EclipseSource and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* EclipseSource - initial API and implementation
******************************************************************************/
package com.eclipsesource.tabris.tracking;
import static com.eclipsesource.tabris.internal.Clauses.when;
import static com.eclipsesource.tabris.internal.Clauses.whenNull;
import java.io.Serializable;
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.rap.rwt.RWT;
import org.eclipse.rap.rwt.service.ApplicationContext;
import org.eclipse.rap.rwt.service.UISession;
import org.eclipse.swt.widgets.Display;
import com.eclipsesource.tabris.TabrisClient;
import com.eclipsesource.tabris.tracking.TrackingEvent.EventType;
import com.eclipsesource.tabris.tracking.internal.DispatchTask;
import com.eclipsesource.tabris.tracking.internal.EventDispatcher;
import com.eclipsesource.tabris.tracking.internal.EventDispatcherProvider;
import com.eclipsesource.tabris.tracking.internal.TrackingInfoFactory;
import com.eclipsesource.tabris.tracking.tracker.ConsoleTracker;
import com.eclipsesource.tabris.tracking.tracker.GoogleAnalyticsTracker;
import com.eclipsesource.tabris.tracking.tracker.PiwikTracker;
import com.eclipsesource.tabris.ui.Action;
import com.eclipsesource.tabris.ui.ActionConfiguration;
import com.eclipsesource.tabris.ui.Page;
import com.eclipsesource.tabris.ui.PageConfiguration;
import com.eclipsesource.tabris.ui.TransitionAdapter;
import com.eclipsesource.tabris.ui.UI;
import com.eclipsesource.tabris.ui.UIConfiguration;
import com.eclipsesource.tabris.ui.action.SearchActionListener;
/**
*
* A {@link Tracking} is responsible for tracking UI events. UI events are fired e.g. when a user navigates through an
* app or a button was pressed. A {@link Tracking} can be attached to a {@link UIConfiguration} which starts an
* automated tracking for the associated Tabris UI. Besides the automated tracking you can use a {@link Tracking}
* instance to fire custom or ecommerce events.
*
*
* A tracking always needs one or more concrete {@link Tracker} instances to delegate the events. The {@link Tracking}
* handles all scheduling and threading topics. It creates a {@link TrackingEvent} for every UI event and dispatches it
* to the added {@link Tracker} instances.
*
*
* Please Note: You should create only one {@link Tracking} per application, not per {@link UISession}.
* Consider sharing the {@link Tracking} instance as attribute in the {@link ApplicationContext}.
*
*
* Usually the {@link Tracking} will be used with popular tracking services like
* Google Analytics or Piwik. For this
* reason some ready to use {@link Tracker} implementations exist:
*
* - {@link GoogleAnalyticsTracker}
* - {@link PiwikTracker}
* - {@link ConsoleTracker}
*
*
*
* A simple example using the {@link ConsoleTracker} looks like this:
*
* ...
* Tracking tracking = new Tracking( new ConsoleTracker() );
* tracking.attach( myUIConfiguration );
* RWT.getApplicationContext().setAttribute( "tracking", tracking );
* ...
*
*
*
* @see Tracker
*
* @since 1.4
*/
@SuppressWarnings("restriction")
public class Tracking implements Serializable {
private final EventDispatcher dispatcher;
private final List trackers;
/**
*
* Creates a {@link Tracking} instance with one {@link Tracker}.
*
*
* @param tracker the tracker to use. Must not be null
.
*/
public Tracking( Tracker tracker ) {
this( tracker, new Tracker[] {} );
}
/**
*
* Creates a {@link Tracking} instance with one or more {@link Tracker}.
*
*
* @param tracker the tracker to use. Must not be null
.
* @param otherTrackers additional {@link Tracker} to use. Must not be null
.
*/
public Tracking( Tracker tracker, Tracker... otherTrackers ) {
this( EventDispatcherProvider.getDispatcher(), createTrackerList( tracker, otherTrackers ) );
}
Tracking( EventDispatcher disptacher, List trackers ) {
this.dispatcher = disptacher;
this.trackers = trackers;
}
private static List createTrackerList( Tracker tracker, Tracker... otherTrackers ) {
whenNull( tracker ).throwIllegalArgument( "Tracker must not be null." );
whenNull( otherTrackers ).throwIllegalArgument( "OtherTrackers must not be null." );
List trackers = new ArrayList();
trackers.add( tracker );
trackers.addAll( Arrays.asList( otherTrackers ) );
return trackers;
}
/**
*
* A {@link TrackingEvent} will be processed asynchronous. A {@link Tracker} implementation can throw exceptions when
* something goes wrong. To prevent failures you can set an {@link UncaughtExceptionHandler} to catch those
* and handle those exceptions properly.
*
*
* @param exceptionHandler the exception handler to use for error handling. Must not be null
.
*/
public void setUncaughtExceptionHandler( UncaughtExceptionHandler exceptionHandler ) {
whenNull( exceptionHandler ).throwIllegalArgument( "ExceptionHandler must not be null." );
dispatcher.setUncaughtExceptionHandler( exceptionHandler );
}
/**
*
* To track ecommerce events you can submit orders e.g. within you shop application.
*
*
* @param display the display of the {@link UISession} the order was made in. Must not be null
.
* @param order the {@link Order} to track. Must not be null
.
*/
public void submitOrder( Display display, Order order ) {
whenNull( display ).throwIllegalArgument( "Display must not be null" );
whenNull( order ).throwIllegalArgument( "Order must not be null" );
TrackingInfo info = createInfo( display );
dispatchEvent( EventType.ORDER, info, order );
}
/**
*
* Within you application you may want to track custom events e.g. when a special button was pressed and so on.
* To accomplish this you can submit events with a custom id.
*
*
* @param display the display of the {@link UISession} the order was made in. Must not be null
.
* @param eventId the custom event id. Must not be null
or empty.
*/
public void submitEvent( Display display, String eventId ) {
whenNull( display ).throwIllegalArgument( "Display must not be null" );
whenNull( eventId ).throwIllegalArgument( "EventId must not be null" );
when( eventId.isEmpty() ).throwIllegalArgument( "EventId must not be empty" );
TrackingInfo info = createInfo( display );
dispatchEvent( EventType.EVENT, info, eventId );
}
/**
*
* To track Tabris UI navigation and action events you can attach a {@link UIConfiguration} to a {@link Tracking}
* instance. The {@link Tracking} will dispatch all {@link Page} navigations, {@link Action} executions and searches
* to the added {@link Tracker}s.
*
*
* @param configuration the configuration of the Tabris UI to track. Must not be null
.
*/
public void attach( UIConfiguration configuration ) {
whenNull( configuration ).throwIllegalArgument( "UIConfiguration must not be null." );
configuration.addTransitionListener( createTransitionListener() );
configuration.addActionListener( createActionListener() );
}
private TransitionAdapter createTransitionListener() {
return new TransitionAdapter() {
@Override
public void after( UI ui, Page from, Page to ) {
if( RWT.getClient() instanceof TabrisClient ) {
dispatchPageView( ui, to );
}
}
};
}
private SearchActionListener createActionListener() {
return new SearchActionListener() {
@Override
public void executed( UI ui, Action action ) {
if( RWT.getClient() instanceof TabrisClient ) {
dispatchAction( ui, action );
}
}
@Override
public void searched( UI ui, Action action, String query ) {
if( RWT.getClient() instanceof TabrisClient ) {
dispatchSearch( ui, action, query );
}
}
@Override
public void modified( UI ui, Action action, String query ) {
// not used for tracking
}
};
}
private void dispatchPageView( UI ui, Page to ) {
PageConfiguration pageConfiguration = ui.getPageConfiguration( to );
dispatchEvent( EventType.PAGE_VIEW, createInfo( ui.getDisplay() ), pageConfiguration.getId() );
}
private void dispatchAction( UI ui, Action action ) {
ActionConfiguration actionConfiguration = ui.getActionConfiguration( action );
dispatchEvent( EventType.ACTION, createInfo( ui.getDisplay() ), actionConfiguration.getId() );
}
private void dispatchSearch( UI ui, Action action, String query ) {
ActionConfiguration actionConfiguration = ui.getActionConfiguration( action );
TrackingInfo info = createInfo( ui.getDisplay() );
info.setSearchQuery( query );
dispatchEvent( EventType.SEARCH, info, actionConfiguration.getId() );
}
private TrackingInfo createInfo( Display display ) {
return TrackingInfoFactory.createInfo( display );
}
private void dispatchEvent( EventType type, TrackingInfo info, Object detail ) {
TrackingEvent event = new TrackingEvent( type, info, detail, System.currentTimeMillis() );
dispatcher.dispatch( new DispatchTask( trackers, event ) );
}
List getTrackers() {
return trackers;
}
}