Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
46be47c
Added TRAIN_TRACKS_RENDER and TRAIN_TRACKS_INTERACT to AnalyticsTracker
nbradbury Sep 6, 2016
4b24e11
Added AnalyticsRailcar model
nbradbury Sep 6, 2016
5b5082e
Added TRAIN_TRACKS_RENDER and TRAIN_TRACKS_INTERACT to nosara tracker
nbradbury Sep 6, 2016
5bbf9be
Added TRAIN_TRACKS_RENDER and TRAIN_TRACKS_INTERACT to mixpanel tracker
nbradbury Sep 6, 2016
5de0541
Moved model, added trackWithRailcar
nbradbury Sep 6, 2016
de05d9d
Changed AnalyticsRailcar to never return null for String getters
nbradbury Sep 6, 2016
1aeda0c
Added railcarJson to ReaderPost model
nbradbury Sep 6, 2016
14a9b02
Added railcar_json to post table
nbradbury Sep 6, 2016
a1c50c2
Include railcar if it exists when tracking reader post details
nbradbury Sep 6, 2016
5130313
Removed AnalyticsRailcar model
nbradbury Sep 6, 2016
1ceefab
Only track railcar for interact/render events
nbradbury Sep 6, 2016
338d704
Track TRAIN_TRACKS_RENDER when a post with a railcar is rendered
nbradbury Sep 6, 2016
dd045b5
Added trackRailcarInteract(), required changing AnalyticsTrackerNosar…
nbradbury Sep 6, 2016
5163039
Call trackRailcarInteract when tracking reader post event
nbradbury Sep 6, 2016
4a0dfaa
Use trackWithReaderPostDetails when tracking a post being liked/unliked
nbradbury Sep 6, 2016
2a36994
Use trackWithReaderPostDetails when tracking a search result being ta…
nbradbury Sep 6, 2016
86e9551
Removed unused canTrackRailcarInteract from trackWithBlogDetails
nbradbury Sep 6, 2016
27518d3
Use HashSet to store rendered post IDs
nbradbury Sep 6, 2016
e0eeb42
Renamed "Interact" to "Interaction"
nbradbury Sep 6, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
*/
public class ReaderDatabase extends SQLiteOpenHelper {
protected static final String DB_NAME = "wpreader.db";
private static final int DB_VERSION = 124;
private static final int DB_VERSION = 125;

/*
* version history
Expand Down Expand Up @@ -76,6 +76,7 @@ public class ReaderDatabase extends SQLiteOpenHelper {
* 122 - changed tbl_posts primary key to pseudo_id
* 123 - changed tbl_posts.published to tbl_posts.date
* 124 - returned tbl_posts.published
* 125 - added tbl_posts.railcar_json
*/

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ public class ReaderPostTable {
+ "attachments_json," // 34
+ "discover_json," // 35
+ "xpost_post_id," // 36
+ "xpost_blog_id"; // 37
+ "xpost_blog_id," // 37
+ "railcar_json"; // 38

// used when querying multiple rows and skipping tbl_posts.text
private static final String COLUMN_NAMES_NO_TEXT =
Expand Down Expand Up @@ -102,7 +103,8 @@ public class ReaderPostTable {
+ "tbl_posts.attachments_json," // 33
+ "tbl_posts.discover_json," // 34
+ "tbl_posts.xpost_post_id," // 35
+ "tbl_posts.xpost_blog_id"; // 36
+ "tbl_posts.xpost_blog_id," // 36
+ "tbl_posts.railcar_json"; // 37

protected static void createTables(SQLiteDatabase db) {
db.execSQL("CREATE TABLE tbl_posts ("
Expand Down Expand Up @@ -143,6 +145,7 @@ protected static void createTables(SQLiteDatabase db) {
+ " discover_json TEXT,"
+ " xpost_post_id INTEGER DEFAULT 0,"
+ " xpost_blog_id INTEGER DEFAULT 0,"
+ " railcar_json TEXT,"
+ " PRIMARY KEY (pseudo_id)"
+ ")");

Expand Down Expand Up @@ -642,7 +645,7 @@ public static void addOrUpdatePosts(final ReaderTag tag, ReaderPostList posts) {
SQLiteStatement stmtPosts = db.compileStatement(
"INSERT OR REPLACE INTO tbl_posts ("
+ COLUMN_NAMES
+ ") VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12,?13,?14,?15,?16,?17,?18,?19,?20,?21,?22,?23,?24,?25,?26,?27,?28,?29,?30,?31,?32,?33,?34,?35,?36,?37)");
+ ") VALUES (?1,?2,?3,?4,?5,?6,?7,?8,?9,?10,?11,?12,?13,?14,?15,?16,?17,?18,?19,?20,?21,?22,?23,?24,?25,?26,?27,?28,?29,?30,?31,?32,?33,?34,?35,?36,?37,?38)");
SQLiteStatement stmtTags = db.compileStatement(
"INSERT OR REPLACE INTO tbl_post_tags (post_id, blog_id, feed_id, pseudo_id, tag_name, tag_type) VALUES (?1,?2,?3,?4,?5,?6)");

Expand Down Expand Up @@ -687,6 +690,7 @@ public static void addOrUpdatePosts(final ReaderTag tag, ReaderPostList posts) {
stmtPosts.bindString(35, post.getDiscoverJson());
stmtPosts.bindLong (36, post.xpostPostId);
stmtPosts.bindLong (37, post.xpostBlogId);
stmtPosts.bindString(38, post.getRailcarJson());
stmtPosts.execute();
}

Expand Down Expand Up @@ -907,6 +911,8 @@ private static ReaderPost getPostFromCursor(Cursor c) {
post.xpostPostId = c.getLong(c.getColumnIndex("xpost_post_id"));
post.xpostBlogId = c.getLong(c.getColumnIndex("xpost_blog_id"));

post.setRailcarJson(c.getString(c.getColumnIndex("railcar_json")));

return post;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import org.wordpress.android.ui.reader.utils.ImageSizeMap;
import org.wordpress.android.ui.reader.utils.ReaderImageScanner;
import org.wordpress.android.ui.reader.utils.ReaderUtils;
import org.wordpress.android.util.AppLog;
import org.wordpress.android.util.DateTimeUtils;
import org.wordpress.android.util.GravatarUtils;
import org.wordpress.android.util.HtmlUtils;
Expand Down Expand Up @@ -75,6 +74,8 @@ public class ReaderPost {
public long xpostPostId;
public long xpostBlogId;

private String railcarJson;

public static ReaderPost fromJson(JSONObject json) {
if (json == null) {
throw new IllegalArgumentException("null json post");
Expand Down Expand Up @@ -209,6 +210,12 @@ public static ReaderPost fromJson(JSONObject json) {
.getLargestImage(ReaderConstants.MIN_FEATURED_IMAGE_WIDTH);
}

// "railcar" data - currently used in search streams, used by TrainTracks
JSONObject jsonRailcar = json.optJSONObject("railcar");
if (jsonRailcar != null) {
post.setRailcarJson(jsonRailcar.toString());
}

return post;
}

Expand Down Expand Up @@ -604,6 +611,17 @@ public boolean canLikePost() {
return (isWP() || isJetpack) && (!isDiscoverPost());
}


public String getRailcarJson() {
return StringUtils.notNullStr(railcarJson);
}
public void setRailcarJson(String jsonRailcar) {
this.railcarJson = StringUtils.notNullStr(jsonRailcar);
}
public boolean hasRailcar() {
return !TextUtils.isEmpty(railcarJson);
}

/****
* the following are transient variables - not stored in the db or returned in the json - whose
* sole purpose is to cache commonly-used values for the post that speeds up using them inside
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -353,9 +353,9 @@ private void togglePostLike() {
refreshIconCounts();

if (isAskingToLike) {
AnalyticsUtils.trackWithBlogDetails(AnalyticsTracker.Stat.READER_ARTICLE_LIKED, mBlogId);
AnalyticsUtils.trackWithReaderPostDetails(AnalyticsTracker.Stat.READER_ARTICLE_LIKED, mPost);
} else {
AnalyticsUtils.trackWithBlogDetails(AnalyticsTracker.Stat.READER_ARTICLE_UNLIKED, mBlogId);
AnalyticsUtils.trackWithReaderPostDetails(AnalyticsTracker.Stat.READER_ARTICLE_UNLIKED, mPost);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1444,7 +1444,7 @@ public void onPostSelected(ReaderPost post) {
post.postId);
break;
case SEARCH_RESULTS:
AnalyticsTracker.track(AnalyticsTracker.Stat.READER_SEARCH_RESULT_TAPPED);
AnalyticsUtils.trackWithReaderPostDetails(AnalyticsTracker.Stat.READER_SEARCH_RESULT_TAPPED, post);
ReaderActivityLauncher.showReaderPostDetail(getActivity(), post.blogId, post.postId);
break;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@
import org.wordpress.android.util.UrlUtils;
import org.wordpress.android.widgets.WPNetworkImageView;

import java.util.HashSet;

public class ReaderPostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private ReaderTag mCurrentTag;
private long mCurrentBlogId;
Expand All @@ -64,6 +66,7 @@ public class ReaderPostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol

private final ReaderTypes.ReaderPostListType mPostListType;
private final ReaderPostList mPosts = new ReaderPostList();
private final HashSet<String> mRenderedIds = new HashSet<>();

private ReaderInterfaces.OnPostSelectedListener mPostSelectedListener;
private ReaderInterfaces.OnTagSelectedListener mOnTagSelectedListener;
Expand Down Expand Up @@ -456,6 +459,13 @@ public void onClick(View v) {
});

checkLoadMore(position);

// if we haven't already rendered this post and it has a "railcar" attached to it, add it
// to the rendered list and record the TrainTracks render event
if (post.hasRailcar() && !mRenderedIds.contains(post.getPseudoId())) {
mRenderedIds.add(post.getPseudoId());
AnalyticsUtils.trackRailcarRender(post.getRailcarJson());
}
}

/*
Expand Down Expand Up @@ -604,6 +614,7 @@ private ReaderTypes.ReaderPostListType getPostListType() {
public void setCurrentTag(ReaderTag tag) {
if (!ReaderTag.isSameTag(tag, mCurrentTag)) {
mCurrentTag = tag;
mRenderedIds.clear();
reload();
}
}
Expand All @@ -617,6 +628,7 @@ public void setCurrentBlogAndFeed(long blogId, long feedId) {
if (blogId != mCurrentBlogId || feedId != mCurrentFeedId) {
mCurrentBlogId = blogId;
mCurrentFeedId = feedId;
mRenderedIds.clear();
reload();
}
}
Expand Down Expand Up @@ -758,7 +770,7 @@ public void onClick(View v) {
/*
* triggered when user taps the like button (textView)
*/
private void toggleLike(Context context, ReaderPostViewHolder holder,ReaderPost post) {
private void toggleLike(Context context, ReaderPostViewHolder holder, ReaderPost post) {
if (post == null || !NetworkUtils.checkConnection(context)) {
return;
}
Expand All @@ -773,12 +785,12 @@ private void toggleLike(Context context, ReaderPostViewHolder holder,ReaderPost
}

if (isAskingToLike) {
AnalyticsUtils.trackWithBlogDetails(AnalyticsTracker.Stat.READER_ARTICLE_LIKED, mCurrentBlogId != 0 ? mCurrentBlogId : null);
AnalyticsUtils.trackWithReaderPostDetails(AnalyticsTracker.Stat.READER_ARTICLE_LIKED, post);
// Consider a like to be enough to push a page view - solves a long-standing question
// from folks who ask 'why do I have more likes than page views?'.
ReaderPostActions.bumpPageViewForPost(post);
} else {
AnalyticsUtils.trackWithBlogDetails(AnalyticsTracker.Stat.READER_ARTICLE_LIKED, mCurrentBlogId != 0 ? mCurrentBlogId : null);
AnalyticsUtils.trackWithReaderPostDetails(AnalyticsTracker.Stat.READER_ARTICLE_LIKED, post);
}

// update post in array and on screen
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,32 @@

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.AnalyticsMetadata;
import org.wordpress.android.analytics.AnalyticsTrackerNosara;
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_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";
Expand Down Expand Up @@ -186,6 +199,72 @@ public static void trackWithReaderPostDetails(AnalyticsTracker.Stat stat, Reader
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());
}
}

/**
* 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;
}

/*
* 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()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any performance impact here? I'm assuming it's really lightweight json objects.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they're fairly lightweight. Here's an example from a post returned by /v1.2/read/search/?q=android:

screen shot 2016-09-09 at 6 04 35 pm

String key = iter.next();
Object value = jsonRailcar.get(key);
properties.put(key, value);
}
} catch (JSONException e) {
AppLog.e(AppLog.T.READER, e);
}

return properties;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,9 @@ public enum Stat {
SITE_SETTINGS_DELETE_SITE_REQUESTED,
SITE_SETTINGS_DELETE_SITE_RESPONSE_OK,
SITE_SETTINGS_DELETE_SITE_RESPONSE_ERROR,
ABTEST_START
ABTEST_START,
TRAIN_TRACKS_RENDER,
TRAIN_TRACKS_INTERACT
}

private static final List<Tracker> TRACKERS = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,10 @@ private AnalyticsTrackerMixpanelInstructionsForStat instructionsForStat(
case ABTEST_START:
instructions = AnalyticsTrackerMixpanelInstructionsForStat.mixpanelInstructionsForEventName("AB Test - Started");
break;
case TRAIN_TRACKS_RENDER: case TRAIN_TRACKS_INTERACT:
// Do nothing. These events are just for Tracks.
instructions = null;
break;
default:
instructions = null;
break;
Expand Down
Loading