How to track user visit duration in sitecore analytics - sitecore

We need to track all users(anonymous and authenticated) who spent more than 2 minutes on the site? Is it possible through OOB ways of Sitecore or do we need to write any custom pipeline\processor?
If custom way, what's the best pipeline to override(Session End or VisitEnd pipeline of analytics) and also how to calculate the user session duration?which attribute would give the exact time details?

Sitecore will keep track of the time spent for you in the tracker. In Tracker.Current.Interaction you will find the StartDateTime, EndDateTime and even the SaveDateTime if you would need that.
Of course, this measurement is only final when the user ends his visit. So how to handle this information depends on what you actually want to do with it. You say "track", so that is done. The data is in the database..

Concerning how to calculate the user session duration:
Tracker.Current.Session.Interaction.Pages.Sum((Page page) => page.Duration / 1000);
It will return number of seconds.
If your scenario is something like "after user spent 2 minutes on the site we want to show him advertisement" you should use Sitecore rules engine and exactly VisitDuration condition.

Related

Ember JS : Lazy load Model data

I'm trying to render ember model data which has more than 1000 records. This will take more than 2 min to finish the rendering part.
So, I have a plan to optimize it. I want to load the first 100 records in the first time. Once they go to the end then I need to load the second 100 records.
How can I do that?
Retrieving pages of data
The concept is paging and depends on how your backend handles paging. But in the generic case, something like:
let result = this.store.query('post', {
limit: 10,
offset: 0
});
once processed by the backend would result in a query to a relational database like:
SELECT * FROM post LIMIT 10 OFFSET 0;
So, you will need to keep track of the current page you are showing. Each time you want to fetch a new page, you will simply increment your offset by page * limit where page is the current page index. So the next query when page = 1 would be:
let result = this.store.query('post', {
limit: 10,
offset: 10 // 1 * 10
});
It's probably a good idea for you backend to return the total result count, which you can access via some kind metadata key on your JSON responses (or however you want since it depends on the way your backend speaks collections). This way you know when to stop trying to fetch the next page.
UX around retrieval
You will need to choose whether you want to do simple paging, which supplies a next and previous button that the user clicks on to retrieve the next / previous page. Probably best UX to manage the page with query params so that the forward/back buttons in the browser move pages and refreshing does not lose the page. You should also disable / enable the previous and next buttons when there are no pages to fetch in either direction.
Pros
easy to develop
user never loses their place
since only ever showing one page at a time, no memory / performance concerns
Cons
users have to click buttons and may choose not to / not realize how
Addons
ember-cli-pagination
The alternative would be using infinite scrolling (a la Facebook news feed). You must pay attention to the scrolling position to know when to fetch the next view (which requires math around the sizes of the current items). Alternatively, you evaluate whether item n - 2 or something like that is in the view port and then prefetch the next page.
Pros
users never think about paging and continue seeing new content with ease
Cons
horrible for returning to ones spot on page change / refresh
horrible for searching
requires a great deal of attention to the amount of data you are showing or else you will run into overconsumption of memory and performance degradation.
more difficult to write since you must handle scrolling events, view port detection, etc
addons
ember-in-viewport
vertical-collection
ember-infinity

NoSQL Race Condition

I'm trying to figure out how companies that use nosql database solve this general nosql race condition issue:
Lucky example: User and Product. Product has quantity of 1 and there are 2 users. When the first user tries to buy this product, system first checks whether quantity is > 0 and it is indeed > 0, proceeds to create a Transaction object and decrement quantity of product. The second user tries to buy the product, system rejects as quantity isn't > 0.
Unlucky: Both users try to buy the product simultaneously. For both, system confirmed quantity is > 0 and so created a Transaction object for both users, hence destroying the company image next day...
How to generally deal with this common scenario?
From similar cases i found on the net, one suggested solution is to use request queue, and process the request one by one. However, if all transactions are queued, and you're running business like Amazon (millions of transactions every now and then), how do we expect users to know whether or not their purchase succeeded shortly after they clicked that purchase now button?
One of the ways to solve this problem is to allow both users to order products simultaneously.
Then there are two possible situations:
One of the users doesn't finish a transaction (refuses to pay, closes a browser window etc). Then another one will have the requested amount of a product.
Both users finished their transactions. Then you will get a random user your product and say sorry to another one giving away a coupon with $10 to him/her.
The second situation should happen extremely rare. So you won't blow out all your money on coupons and your users will be happy whatever the outcome. But you still need to monitor the 2nd situation in order to react and make changes to your system if it happens more often than you expected.

Overcoming querying limitations in Couchbase

We recently made a shift from relational (MySQL) to NoSQL (couchbase). Basically its a back-end for social mobile game. We were facing a lot of problems scaling our backend to handle increasing number of users. When using MySQL loading a user took a lot of time as there were a lot of joins between multiple tables. We saw a huge improvement after moving to couchbase specially when loading data as most of it is kept in a single document.
On the downside, couchbase also seems to have a lot of limitations as far as querying is concerned. Couchbase alternative to SQL query is views. While we managed to handle most of our queries using map-reduce, we are really having a hard time figuring out how to handle time based queries. e.g. we need to filter users based on timestamp attribute. We only need a user in view if time is less than current time:
if(user.time < new Date().getTime() / 1000)
What happens is that once a user's time is set to some future time, it gets exempted from this view which is the desired behavior but it never gets added back to view unless we update it - a document only gets re-indexed in view when its updated.
Our solution right now is to load first x user documents and then check time in our application. Sorting is done on user.time attribute so we get those users who's time is less than or near to current time. But I am not sure if this is actually going to work in live environment. Ideally we would like to avoid these type of checks at application level.
Also there are times e.g. match making when we need to check multiple time based attributes. Our current strategy doesn't work in such cases and we frequently get documents from view which do not pass these checks when done in application. I would really appreciate if someone who has already tackled similar problems could share their experiences. Thanks in advance.
Update:
We tried using range queries which works for only one key. Like I said in most cases we have multiple time based keys meaning multiple ranges which does not work.
If you use Date().getTime() inside a view function, you'll always get the time when that view was indexed, just as you said "it never gets added back to view unless we update it".
There are two ways:
Bad way (don't do this in production). Query views with stale=false param. That will cause view to update before it will return results. But view indexing is slow process, especially if you have > 1 milllion records.
Good way. Use range requests. You just need to emit your date in map function as a key or a part of complex key and use that range request. You can see one example here or here (also if you want to use DateTime in couchbase this example will be more usefull). Or just look to my example below:
I.e. you will have docs like:
doc = {
"id"=1,
"type"="doctype",
"timestamp"=123456, //document update or creation time
"data"="lalala"
}
For those docs map function will look like:
map = function(){
if (doc.type === "doctype"){
emit(doc.timestamp,null);
}
}
And now to get recently "updated" docs you need to query this view with params:
startKey="dateTimeNowFromApp"
endKey="{}"
descending=true
Note that startKey and endKey are swapped, because I used descending order. Here is also a link to documnetation about key types that couchbase supports.
Also I've found a link to a question that can also help.

Querying earliest post of a Facebook user using Facebook Graph API or FQL

I would like to query earliest posts of a Facebook user using FQL or Graph API. The big issue is by default, Facebook limit return items, which are ordered by descending time.
I know I can limit my query by until, but I don't know what date to put in, because I have no idea when my user become Facebook member. I have to do search like:
find post until Jan 2006
if null, then find post until Jan 2007
if null, then find post until Jan 2008
....
which I hate so much.
Is there a smarter way to find out earliest posts by user?
First off, it's near impossible to have an all encompassing program that determines when a user joined Facebook, to put it quite bluntly. I know from your past questions, you have been trying but many have tried before you, it's not possible.
For example what happens if no one decides to write anything on my wall from the date I joined to 1 year after? That indicator becomes pretty inaccurate now does it?
Anything smarter is based on assumptions that may or may not hold true.
e.g.
Assumption 1: Every Facebook user would publish a post on or near when they joined
this give an initial guess based on A1
Assumptions 2: Given A1, any post by a friend on a user's wall that is posted before the unix time returned by A1 will be earlier in date
this will always be true as long as A1 holds.
All of this falls when there is a year between actual activity and join date.
You can minimize the set returned by calling less data per item and more items overall
/me/feed?fields=created_time&limit=200
Then you page until there is no next paging parameter left.
If you are indeed trying to find when did a user join Facebook, I agree with phwd's answer.
The best way I have been able to find out (which is also cheaper than having to reiterate through tons of posts) is accessing the earliest "profile pictures" of the user. This is making the assumption that a user would post a profile picture soon after creating their account.
Once you can get access to "Profile Pictures" album, you might be able to use created_time field for the album (or sort Profile Pictures by created_time for individual photos).
Even if the earliest photo was deleted, what are the chances that the user stays without any profile picture for a long time?
Reference:
https://developers.facebook.com/docs/graph-api/reference/v2.0/album

Find User's First Post?

Using the Graph API or FQL, is there a way to efficiently find a user's first post or status? As in, the first one they ever made?
The slow way, I assume, would be to paginate through the feed, but for users like me who joined in 2005 or earlier, that would take a very long time with a huge amount of API calls.
From what I have found, we cannot obtain the date the user registered with Facebook for a good starting point, and we cannot sort by date ascending (not outside of the single page of data returned) to get the oldest post on top.
Is there any reasonable way to do this?
you can use facebook query language (FQL) to get first post information.
Please refer below query for more details :-
SELECT message, time FROM status WHERE uid= me() ORDER BY time ASC LIMIT 1
Please check and let me know in case of any issue.
Thanks and Regards
Durgaprasad
I think the Public API is limited to the depth of information it is allowed to query. Facebook probably put in these constraints for performance and cost concerns. Maybe they've changed it. When I tried to go backwards thru a person's stream about 4 months ago, there seemed to be a limit as to how far back I could go. Maybe it's a time limit or a # posts back limit. If you know when your user first posted, then getting to it should be fairly quick using the since/until time stamps in your queries.