blob: 208605959239861a64d8037b4b8cef3be5d09a55 [file] [log] [blame]
package org.wordpress.android.util;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.text.Html;
import android.text.TextUtils;
import org.json.JSONException;
import org.json.JSONObject;
import org.wordpress.android.WordPress;
import org.wordpress.android.analytics.AnalyticsMetadata;
import org.wordpress.android.analytics.AnalyticsTracker;
import org.wordpress.android.analytics.AnalyticsTrackerMixpanel;
import org.wordpress.android.analytics.AnalyticsTrackerNosara;
import org.wordpress.android.datasets.ReaderPostTable;
import org.wordpress.android.models.AccountHelper;
import org.wordpress.android.models.Blog;
import org.wordpress.android.models.ReaderPost;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import static org.wordpress.android.analytics.AnalyticsTracker.Stat.READER_ARTICLE_COMMENTED_ON;
import static org.wordpress.android.analytics.AnalyticsTracker.Stat.READER_ARTICLE_LIKED;
import static org.wordpress.android.analytics.AnalyticsTracker.Stat.READER_ARTICLE_OPENED;
import static org.wordpress.android.analytics.AnalyticsTracker.Stat.READER_RELATED_POST_CLICKED;
import static org.wordpress.android.analytics.AnalyticsTracker.Stat.READER_SEARCH_RESULT_TAPPED;
import static org.wordpress.android.analytics.AnalyticsTracker.Stat.TRAIN_TRACKS_INTERACT;
import static org.wordpress.android.analytics.AnalyticsTracker.Stat.TRAIN_TRACKS_RENDER;
public class AnalyticsUtils {
private static String BLOG_ID_KEY = "blog_id";
private static String POST_ID_KEY = "post_id";
private static String FEED_ID_KEY = "feed_id";
private static String FEED_ITEM_ID_KEY = "feed_item_id";
private static String IS_JETPACK_KEY = "is_jetpack";
/**
* Utility method to refresh mixpanel metadata.
*
* @param username WordPress.com username
* @param email WordPress.com email address
*/
public static void refreshMetadata(String username, String email) {
AnalyticsMetadata metadata = new AnalyticsMetadata();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(WordPress.getContext());
metadata.setSessionCount(preferences.getInt(AnalyticsTrackerMixpanel.SESSION_COUNT, 0));
metadata.setUserConnected(AccountHelper.isSignedIn());
metadata.setWordPressComUser(AccountHelper.isSignedInWordPressDotCom());
metadata.setJetpackUser(AccountHelper.isJetPackUser());
metadata.setNumBlogs(WordPress.wpDB.getNumBlogs());
metadata.setUsername(username);
metadata.setEmail(email);
AnalyticsTracker.refreshMetadata(metadata);
}
/**
* Utility method to refresh mixpanel metadata.
*/
public static void refreshMetadata() {
AnalyticsMetadata metadata = new AnalyticsMetadata();
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(WordPress.getContext());
metadata.setSessionCount(preferences.getInt(AnalyticsTrackerMixpanel.SESSION_COUNT, 0));
metadata.setUserConnected(AccountHelper.isSignedIn());
metadata.setWordPressComUser(AccountHelper.isSignedInWordPressDotCom());
metadata.setJetpackUser(AccountHelper.isJetPackUser());
metadata.setNumBlogs(WordPress.wpDB.getNumBlogs());
metadata.setUsername(AccountHelper.getDefaultAccount().getUserName());
metadata.setEmail(AccountHelper.getDefaultAccount().getEmail());
AnalyticsTracker.refreshMetadata(metadata);
}
public static int getWordCount(String content) {
String text = Html.fromHtml(content.replaceAll("<img[^>]*>", "")).toString();
return text.split("\\s+").length;
}
/**
* Bump Analytics for the passed Stat and CURRENT blog details into properties.
*
* @param stat The Stat to bump
*
*/
public static void trackWithCurrentBlogDetails(AnalyticsTracker.Stat stat) {
trackWithCurrentBlogDetails(stat, null);
}
/**
* Bump Analytics for the passed Stat and CURRENT blog details into properties.
*
* @param stat The Stat to bump
* @param properties Properties to attach to the event
*
*/
public static void trackWithCurrentBlogDetails(AnalyticsTracker.Stat stat, Map<String, Object> properties) {
trackWithBlogDetails(stat, WordPress.getCurrentBlog(), properties);
}
/**
* Bump Analytics for the passed Stat and add blog details into properties.
*
* @param stat The Stat to bump
* @param blog The blog object
*
*/
public static void trackWithBlogDetails(AnalyticsTracker.Stat stat, Blog blog) {
trackWithBlogDetails(stat, blog, null);
}
/**
* Bump Analytics for the passed Stat and add blog details into properties.
*
* @param stat The Stat to bump
* @param blog The blog object
* @param properties Properties to attach to the event
*
*/
public static void trackWithBlogDetails(AnalyticsTracker.Stat stat, Blog blog, Map<String, Object> properties) {
if (blog == null || (!blog.isDotcomFlag() && !blog.isJetpackPowered())) {
AppLog.w(AppLog.T.STATS, "The passed blog obj is null or it's not a wpcom or Jetpack. Tracking analytics without blog info");
AnalyticsTracker.track(stat, properties);
return;
}
String blogID = blog.getDotComBlogId();
if (blogID != null) {
if (properties == null) {
properties = new HashMap<>();
}
properties.put(BLOG_ID_KEY, blogID);
properties.put(IS_JETPACK_KEY, blog.isJetpackPowered());
} else {
// When the blog ID is null here does mean the blog is not hosted on wpcom.
// It may be a Jetpack blog still in synch for options, or a self-hosted.
// In both of these cases skip adding blog details into properties.
}
if (properties == null) {
AnalyticsTracker.track(stat);
} else {
AnalyticsTracker.track(stat, properties);
}
}
/**
* Bump Analytics and add blog_id into properties
*
* @param stat The Stat to bump
* @param blogID The REMOTE blog ID.
*
*/
public static void trackWithBlogDetails(AnalyticsTracker.Stat stat, Long blogID) {
Map<String, Object> properties = new HashMap<>();
if (blogID != null) {
properties.put(BLOG_ID_KEY, blogID);
}
AnalyticsTracker.track(stat, properties);
}
/**
* Bump Analytics and add blog_id into properties
*
* @param stat The Stat to bump
* @param blogID The REMOTE blog ID.
*
*/
public static void trackWithBlogDetails(AnalyticsTracker.Stat stat, String blogID) {
try {
Long remoteID = Long.parseLong(blogID);
trackWithBlogDetails(stat, remoteID);
} catch (NumberFormatException err) {
AnalyticsTracker.track(stat);
}
}
/**
* Bump Analytics for a reader post
*
* @param stat The Stat to bump
* @param post The reader post to track
*
*/
public static void trackWithReaderPostDetails(AnalyticsTracker.Stat stat, ReaderPost post) {
if (post == null) return;
// wpcom/jetpack posts should pass: feed_id, feed_item_id, blog_id, post_id, is_jetpack
// RSS pass should pass: feed_id, feed_item_id, is_jetpack
Map<String, Object> properties = new HashMap<>();
if (post.isWP() || post.isJetpack) {
properties.put(BLOG_ID_KEY, post.blogId);
properties.put(POST_ID_KEY, post.postId);
}
properties.put(FEED_ID_KEY, post.feedId);
properties.put(FEED_ITEM_ID_KEY, post.feedItemId);
properties.put(IS_JETPACK_KEY, post.isJetpack);
AnalyticsTracker.track(stat, properties);
// record a railcar interact event if the post has a railcar and this can be tracked
// as an interaction
if (canTrackRailcarInteraction(stat) && post.hasRailcar()) {
trackRailcarInteraction(stat, post.getRailcarJson());
}
}
public static void trackWithReaderPostDetails(AnalyticsTracker.Stat stat, long blogId, long postId) {
trackWithReaderPostDetails(stat, ReaderPostTable.getPost(blogId, postId, true));
}
/**
* Track when a railcar item has been rendered
*
* @param post The JSON string of the railcar
*
*/
public static void trackRailcarRender(String railcarJson) {
if (TextUtils.isEmpty(railcarJson)) return;
AnalyticsTracker.track(TRAIN_TRACKS_RENDER, railcarJsonToProperties(railcarJson));
}
/**
* Track when a railcar item has been interacted with
*
* @param stat The event that caused the interaction
* @param post The JSON string of the railcar
*
*/
private static void trackRailcarInteraction(AnalyticsTracker.Stat stat, String railcarJson) {
if (TextUtils.isEmpty(railcarJson)) return;
Map<String, Object> properties = railcarJsonToProperties(railcarJson);
properties.put("action", AnalyticsTrackerNosara.getEventNameForStat(stat));
AnalyticsTracker.track(TRAIN_TRACKS_INTERACT, properties);
}
/**
* @param stat The event that would cause the interaction
* @return True if the passed stat event can be recorded as a railcar interaction
*/
private static boolean canTrackRailcarInteraction(AnalyticsTracker.Stat stat) {
return stat == READER_ARTICLE_LIKED
|| stat == READER_ARTICLE_OPENED
|| stat == READER_SEARCH_RESULT_TAPPED
|| stat == READER_ARTICLE_COMMENTED_ON
|| stat == READER_RELATED_POST_CLICKED;
}
/*
* Converts the JSON string of a railcar to a properties list using the existing json key names
*/
private static Map<String, Object> railcarJsonToProperties(@NonNull String railcarJson) {
Map<String, Object> properties = new HashMap<>();
try {
JSONObject jsonRailcar = new JSONObject(railcarJson);
Iterator<String> iter = jsonRailcar.keys();
while (iter.hasNext()) {
String key = iter.next();
Object value = jsonRailcar.get(key);
properties.put(key, value);
}
} catch (JSONException e) {
AppLog.e(AppLog.T.READER, e);
}
return properties;
}
}