diff options
author | Nick Bradbury <nbradbury@users.noreply.github.com> | 2016-09-11 22:03:10 -0400 |
---|---|---|
committer | Dan Roundhill <dan@automattic.com> | 2016-09-11 19:03:10 -0700 |
commit | 6bb1957779ff42042ff9384b4c68f9de264d9ca1 (patch) | |
tree | 63ba42460573cbbd98ba3fc2416b4bc98673a339 /WordPress/src/main/java | |
parent | 2c5b50ef248202cc0135160a761b02cdfb3c2621 (diff) | |
download | gradle-perf-android-medium-6bb1957779ff42042ff9384b4c68f9de264d9ca1.tar.gz |
Issue/4462 reader traintracks (#4540)
* Added TRAIN_TRACKS_RENDER and TRAIN_TRACKS_INTERACT to AnalyticsTracker
* Added AnalyticsRailcar model
* Added TRAIN_TRACKS_RENDER and TRAIN_TRACKS_INTERACT to nosara tracker
* Added TRAIN_TRACKS_RENDER and TRAIN_TRACKS_INTERACT to mixpanel tracker
* Moved model, added trackWithRailcar
* Changed AnalyticsRailcar to never return null for String getters
* Added railcarJson to ReaderPost model
* Added railcar_json to post table
* Include railcar if it exists when tracking reader post details
* Removed AnalyticsRailcar model
* Only track railcar for interact/render events
* Track TRAIN_TRACKS_RENDER when a post with a railcar is rendered
* Added trackRailcarInteract(), required changing AnalyticsTrackerNosara to return event name
* Call trackRailcarInteract when tracking reader post event
* Use trackWithReaderPostDetails when tracking a post being liked/unliked
* Use trackWithReaderPostDetails when tracking a search result being tapped
* Removed unused canTrackRailcarInteract from trackWithBlogDetails
* Use HashSet to store rendered post IDs
* Renamed "Interact" to "Interaction"
Diffstat (limited to 'WordPress/src/main/java')
7 files changed, 128 insertions, 12 deletions
diff --git a/WordPress/src/main/java/org/wordpress/android/datasets/ReaderDatabase.java b/WordPress/src/main/java/org/wordpress/android/datasets/ReaderDatabase.java index ef9504c37..9ae4f5521 100644 --- a/WordPress/src/main/java/org/wordpress/android/datasets/ReaderDatabase.java +++ b/WordPress/src/main/java/org/wordpress/android/datasets/ReaderDatabase.java @@ -19,7 +19,7 @@ import java.io.OutputStream; */ 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 @@ -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 */ /* diff --git a/WordPress/src/main/java/org/wordpress/android/datasets/ReaderPostTable.java b/WordPress/src/main/java/org/wordpress/android/datasets/ReaderPostTable.java index 1cd234f53..af9b06891 100644 --- a/WordPress/src/main/java/org/wordpress/android/datasets/ReaderPostTable.java +++ b/WordPress/src/main/java/org/wordpress/android/datasets/ReaderPostTable.java @@ -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 = @@ -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 (" @@ -143,6 +145,7 @@ public class ReaderPostTable { + " discover_json TEXT," + " xpost_post_id INTEGER DEFAULT 0," + " xpost_blog_id INTEGER DEFAULT 0," + + " railcar_json TEXT," + " PRIMARY KEY (pseudo_id)" + ")"); @@ -642,7 +645,7 @@ public class ReaderPostTable { 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)"); @@ -687,6 +690,7 @@ public class ReaderPostTable { stmtPosts.bindString(35, post.getDiscoverJson()); stmtPosts.bindLong (36, post.xpostPostId); stmtPosts.bindLong (37, post.xpostBlogId); + stmtPosts.bindString(38, post.getRailcarJson()); stmtPosts.execute(); } @@ -907,6 +911,8 @@ public class ReaderPostTable { 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; } diff --git a/WordPress/src/main/java/org/wordpress/android/models/ReaderPost.java b/WordPress/src/main/java/org/wordpress/android/models/ReaderPost.java index a0b95e7e6..8ce09db51 100644 --- a/WordPress/src/main/java/org/wordpress/android/models/ReaderPost.java +++ b/WordPress/src/main/java/org/wordpress/android/models/ReaderPost.java @@ -10,7 +10,6 @@ import org.wordpress.android.ui.reader.models.ReaderBlogIdPostId; 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; @@ -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"); @@ -209,6 +210,12 @@ public class ReaderPost { .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; } @@ -604,6 +611,17 @@ public class ReaderPost { 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 diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.java index 2ecfec4bd..f88c9baaf 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostDetailFragment.java @@ -353,9 +353,9 @@ public class ReaderPostDetailFragment extends Fragment 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); } } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java index f245cd9ec..69409385e 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/ReaderPostListFragment.java @@ -1444,7 +1444,7 @@ public class ReaderPostListFragment extends Fragment 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; } diff --git a/WordPress/src/main/java/org/wordpress/android/ui/reader/adapters/ReaderPostAdapter.java b/WordPress/src/main/java/org/wordpress/android/ui/reader/adapters/ReaderPostAdapter.java index f2d10a421..090f79fe3 100644 --- a/WordPress/src/main/java/org/wordpress/android/ui/reader/adapters/ReaderPostAdapter.java +++ b/WordPress/src/main/java/org/wordpress/android/ui/reader/adapters/ReaderPostAdapter.java @@ -46,6 +46,8 @@ import org.wordpress.android.util.ToastUtils; 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; @@ -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; @@ -456,6 +459,13 @@ public class ReaderPostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol }); 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()); + } } /* @@ -604,6 +614,7 @@ public class ReaderPostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol public void setCurrentTag(ReaderTag tag) { if (!ReaderTag.isSameTag(tag, mCurrentTag)) { mCurrentTag = tag; + mRenderedIds.clear(); reload(); } } @@ -617,6 +628,7 @@ public class ReaderPostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol if (blogId != mCurrentBlogId || feedId != mCurrentFeedId) { mCurrentBlogId = blogId; mCurrentFeedId = feedId; + mRenderedIds.clear(); reload(); } } @@ -758,7 +770,7 @@ public class ReaderPostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol /* * 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; } @@ -773,12 +785,12 @@ public class ReaderPostAdapter extends RecyclerView.Adapter<RecyclerView.ViewHol } 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 diff --git a/WordPress/src/main/java/org/wordpress/android/util/AnalyticsUtils.java b/WordPress/src/main/java/org/wordpress/android/util/AnalyticsUtils.java index 9348cdc47..c8dd0867a 100644 --- a/WordPress/src/main/java/org/wordpress/android/util/AnalyticsUtils.java +++ b/WordPress/src/main/java/org/wordpress/android/util/AnalyticsUtils.java @@ -2,19 +2,32 @@ 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.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"; @@ -186,6 +199,72 @@ public class AnalyticsUtils { 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()) { + String key = iter.next(); + Object value = jsonRailcar.get(key); + properties.put(key, value); + } + } catch (JSONException e) { + AppLog.e(AppLog.T.READER, e); + } + + return properties; + } + } |