Showing posts with label Engage. Show all posts
Showing posts with label Engage. Show all posts

Saturday, April 29, 2017

Working with timezone for events

Every organization hosts various events; be it for their business growth or some internal functions or other reasons and thus, it very common requirement of client to setup event date-time within WebCenter Sites.

If your client is located only in one country, it is quite easy to setup event date-time as event is usually hosted at same geographical location, thus, you would simply create asset type and definition as needed. While displaying event on your site, you can set fixed desired timezone while formatting date-time using dateformat tags or simply using java.

But if you are dealing with multi-lingual international websites and when client wants to host events for their international counterparts also, displaying event on website pages according to user's geo-location can be a challenging and arduous task.

Although there may be many ways to deal with it and can also vary on client's requirement. I would like to present one working solution which we used in one of our project if you also have the following requirements:
  • editors should be able to set event start and end dates as they desire
  • event should be displayed in end-user's date and time according to where they are geographically located
Hence, basically there are 2 challenges for setting up event date along with timezone:
  1. Saving event date-time considering timezone within WCS
  2. Displaying event date and time on webpage according to user's timezone
Saving event datetime considering timezone within WCS
Dealing with timezone in WCS can be difficult for following reasons:
  1. While setting any date and time for a date attribute within WebCenter Sites, by default DatePicker attribute editor is displayed which provides date, time and seconds to set but lacks an option to set timezone. Thus, it is pretty sad that currently there is no out-of-the-box attribute editor available to set timezone along with date and time.
  2. Even if you set timezone as another attribute, still WCS does not consider it (for obvious reasons) and thus, you would end up manipulating the date attribute's value via flex filter or asset listener or other way.
  3. Furthermore, date attributes within WCS are saved according to the timezone of the application server where WCS is installed and thus, even if you manipulate date attribute according to 2nd step, you will face following issue: Lets suppose if your server timezone is set to UTC and one of the editor located in London sets a time 10:00 AM for an event and saves the asset. Event date is first converted to UTC by WCS and saved in database in server timezone i.e. 11:00 AM UTC. Even if the date is saved in UTC, editor sees the date according to his/her timezone set in his/her profile or automatically calculated by WCS and thus, thinks that event date & time is saved correctly. But now when editor from another location say Germany checks the same asset and verifies the event date, he/she sees the converted date according to his/her timezone i.e. 09:00 AM CEST and thinks that wrong event date or time is set by previous editor? Shouldn't it be 10 AM, why I am seeing 09:00 AM CEST ? and thus, German editor may end up editing the asset or will ask London editor to review and correct it but London editor sees the correct date set. Do you see the issue ?
How to deal with above issues in WCS ?
In order to consider timezone for an event, you would have save the event date-time along with timezone. Developing new DatePicker alike attribute editor with timezone option can be more difficult than the following way:
  1. Create 4 attributes for event definition: 2 attributes of type - date and 2 attributes of type - String. For e.g. eventstartdate and eventenddate of type - string and eventfinalstartdate and eventfinalenddate of type - date
  2. Editors will have to enter values in eventstartdate and eventenddate in some pre-defined specified format for e.g. dd-MM-yyyy HH:mm. Format can be decided with client beforehand. Also, you can add some validation on the input using some custom attribute editor. One such attribute editor is REGEX attribute editor.
  3. Editors should also specify timezone for an event via eventtimezone attribute of type - String. You can assign a pulldown attribute editor with pre-defined timezone values or can dynamically create the item list using TimeZone's method: getAvailableIds and populate them in pulldown attribute editor.
  4. When asset is saved, convert the event's start and end dates + eventtimezone into server timezone and save the value in eventfinalstartdate and eventfinalenddate respectively. You can use either flex filter or call element from PostUpdate element. If you are using Asset API to save date attribute, WCS saves date attribute in following format: yyyy-MM-dd HH:mm:ss. Note, if you are using PostUpdate way, then be sure to make eventfinalstartdate and eventfinalenddate as non-editable fields (How to do so? You can customize the element: OpenMarket/Gator/AttributeTypes/DATEPICKER by creating under CustomElements folder; to make date attribute as non-editable)
Thus, by following above steps, what have we achieved?
  1. eventstartdate and eventenddate is displayed same for all editors irrespective of their timezone set in WCS and thus, there is no conflict among editors.
  2. eventfinalstartdate and eventfinalenddate is saved always in server's timezone and importantly, as date attribute, thus, while displaying date on your webpage, always use eventfinalstartdate and eventfinalendtime.
Why are we saving same values 2 times in 2 different attributes? What do we achieve by doing so?
  • firstly, by saving attributes: eventfinalstartdate and eventfinalenddate of type - date, you can build an event search page where you can sort by date attribute easily which may have been difficult with having only string attributes: eventstartdate and eventenddate.
  • second, when displaying event's date-time, developers can use out-of-the-box dateformat tags which accepts date attribute value as input as is from assetset tags output. Furthermore, dateformat:create tag has ability to input timezone also; which is explained in next section.
Displaying event date and time on webpage according to user's geo-location
After saving event datetime according to previous step, as a developer, its already known that event dates are saved in eventfinalstartdate and eventfinalenddate as date attribute and always in server's timezone.
Thus, for displaying event, we need to:
  • find user's timezone
  • convert and display event dates in user's timezone
For finding user's timezone, there can be various ways but eventually you would have to rely on some geo-location services or other known techniques. One of the element within WebCenter Sites calculates timezone for its various core functionalities is OpenMarket/Xcelerate/Util/SetTimeZoneInSession. You can also use the same. Also, one of the popular known service is Maxmind's GeoIP; which provides quite accurate geo-lcation data and examples on finding user's geo-location data in various programming language.
One important note: If you are using WebCenter Sites 12c, GeoIP is already shipped with the product and can be used for finding user's geo-location information. In fact, we are already using GeoIP API in one of our projects running on WCS 12c for displaying personalised content according to user's geo-location.

After finding user's timezone, you can use following sample code to display the event date-time on your website pages:

I hope this post helps many other fellow WCS enthusiasts who are struggling with dates and timezone :)

Disclaimer: The code and/or the configurations posted are not official recommendations and should be used at sole's discretion with proper testing before deploying on live WebCenter Sites systems. Cheers!!

Monday, September 7, 2015

Content targeting based on clickstream

Every online shopping store has a feature where consumers are shown related items or recommended items as any registered or anonymous users keep on browsing certain items on a website. Such use case are very common and can be developed within WCS or FatWire using Engage.

I am describing a very simple use case using Oracle WCS 11g 11.1.1.6.1 JSK for avisports site. My aim is to record number of times any article (article can be of any type: Running, Football, Skiiing, etc.) was clicked on a particular section and show recommended articles in "you may also like" section on basis of number of clicks + article type.

 Solution can be broken into following steps:
  • Enable visitor attribute, history attribute, history definition, segment and recommendation asset type for AviSport site
  • Add all the required start menus
  • Create visitor attribute - aviarticleuser (string, length-20)
  • Create history attributes - AviArticleType (enumeration - with all the values of ArticleCategory attribute: Category) and AviArticleClickCount (integer)
  • Create one history definition - AviArticleHistory (include AviArticleType and AviArticleClickCount)
  • Create segments for each article category or just create for 2 article category with condition aviarticleuser=<articlecategoryname> (For eg: for baseball segment, add the visitor attribute condtion as aviarticleuser=Baseball and for history definition condition, include count >10 and select "Baseball" as AviArticleType)
  • Create one recommendation asset (mode: recommendation, for asset type: article and select all segments and include corresponding articles and also select some articles for default case)
  • Record anonymous or visitor's clicks at particular section only.
  • Update ArticleLayout to calculate segments and show related articles based on recommendations.

First 7 steps, should be very straightforward. Full details on creating and configuring them is already given in developer's guide.

For recording visitor's click on particular section, I have added one param to Summary/Link (engage = yes) as I would be targeting those visitors who click on Related links section's articles only on any article detail page. Then, add engage parameter to avisports/AVIArticle/GetLink. On clicking article link of related links section, will add one param: engage to the output url, so add that param to ArticleLayout and ArticleLayout2 templates in cache criteria.

Now, update both article layout template to call the element: avisports/getVisitorArticles. This element finds the category of the current article (using query),  then finds the history count (vdm:gethistorycount), records the current article (vdm:recordhistory) to history definition, sets scalar values (vdm:setscalar) which helps while calculating segments, calculates segments (commercecontext:calculatesegments) and then loads list of articles from via recommendation asset (commercecontext:getrecommendations). This whole process of how segments are calculated and recommendations work is well explained in detail in developer's guide.

Futher improvements can be done by calculating segments for the visitor and then calling the template by including the segment id in cache criteria and then loading list of assets from recommendations.

As history definition table is created separately and keeps on adding data exponentially as visitors browse your site, it is better to clean data from this table on timely basis which is explained on my other post: Flushing visitor's data

All the updated elements are bundled here for downloading. I hope this post helps many developers.

Further improvements can be done by using the tag: <commercecontext:setsegments> if you know what segment does a visitor belongs to and then, can add the segment id to cache criteria to leverage the use of OOTB caching of Sites. Discussion on setting segment prior to calculating recommendation is succinctly explained here.

Disclaimer: Any sample code on this blog is not officially recommended, use at your own risk.

Friday, July 3, 2015

Engage: Flushing visitor's data

If you are using Engage, then is one caveat which needs to be taken care of:

"Data in visitor's tables can increase exponentially (obviously depends on how many times your site is visited) which can affect performance"

FatWire/Oracle WCS has no way to know which data is to be deleted and on what basis so basically you have to flush data from tables either manually or by programming. 

Hence, following sample code snippet can help to flush data:

But wait, does admin has to run this code again and again? No. WebCenter Sites has a very important table: SystemEvents where one can add SiteEntry+CSElement or Template and set a time to call this element. Simple, isn't it? So just create an entry in SystemEvents table and some logs, if required.

Tag info: http://docs.oracle.com/cd/E29542_01/apirefs.1111/e39371/JSP/vdm-flushinactive.html
http://docs.oracle.com/cd/E29542_01/apirefs.1111/e39371/JSP/vdm-mergeinactive.html

Disclaimer: Any sample code on this blog is not officially recommended, use at your own risk.

A simple code compare functionality

One of the most important aspect of any development cycle is deployment and while deployment, it is very important to note the changes don...