<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">Blog posts by Hao Peng</title><link href="http://world.optimizely.com" /><updated>2011-12-01T18:20:30.0000000Z</updated><id>https://world.optimizely.com/blogs/Hao-Peng/</id> <generator uri="http://world.optimizely.com" version="2.0">Optimizely World</generator> <entry><title>Facebook Event Attendance Visitor Group Criterion – Part II</title><link href="https://world.optimizely.com/blogs/Hao-Peng/Dates/2011/12/Facebook-Event-Attendance-Visitor-Group-Criterion--Part-II/" /><id>&lt;p&gt;If you have read Part 1 of this article and understood everything there, thanks, bravo and well done! You’ve gone this far so why not continue and finish your reading here. &lt;/p&gt;  &lt;h2&gt;Facebook App and Development&lt;/h2&gt;  &lt;h3&gt;General Principal:&lt;/h3&gt;  &lt;p&gt;A Facebook App is the central concept in order to integrate your site with Facebook. Your website does not know anything about Facebook user profiles, but your App does. The relationship between the site and the Facebook App is established when you create an App. In your website, your code will call Facebook APIs to delegate requests (e.g. getting user events information) to the mapped App. The App will get the information and serialise it to the response using JSON. Your website code will then be able to use capture this response as most commonly JsonArray or JsonObject objects. &lt;/p&gt;  &lt;p&gt;To elaborate, for instance, when your website code sends a request to the Facebook App to request all the Facebook groups a user has joined, the screenshot below shows what is expected in the response. &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/101933cb3d3e4354874fb36619da5405.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/link/2b7497341149475882a9aab6137e29ad.png&quot; width=&quot;472&quot; height=&quot;506&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;This is a serialised JSON string representing a JsonObject object that your website can use. In this case the JsonObject has two key-value pairs. The key for the second pair is “paging”, and its value is to retrieve next 5000 groups the user. More importantly, the key for the first pair is “data”, and its value is an IList object, which can be casted to IDictionary&amp;lt;string, object&amp;gt;. Each entry of this dictionary object represents a Facebook group the user belongs to. &lt;/p&gt;  &lt;p&gt;Sounds complicated? Here is the code to get all the Facebook events a user joined. &lt;/p&gt;  &lt;p align=&quot;left&quot;&gt;FacebookClient fb = new FacebookClient(accessToken);    &lt;br /&gt;JsonObject events = (JsonObject)fb.Get(&amp;quot;/me/events&amp;quot;);     &lt;br /&gt;IList&amp;lt;object&amp;gt; data = (IList&amp;lt;object&amp;gt;)events[&amp;quot;data&amp;quot;];     &lt;br /&gt;IDictionary&amp;lt;string, object&amp;gt; dicEvents = data.Cast&amp;lt;IDictionary&amp;lt;string, object&amp;gt;&amp;gt;(); &lt;/p&gt;  &lt;p align=&quot;left&quot;&gt;So not complicated, is it? &lt;/p&gt;  &lt;h3&gt;Create a Facebook App&lt;/h3&gt;  &lt;p&gt;In order to make the above code work, you will need the access token where your App can use to access the user’s profile. In order to get the access token, let’s first take a look at how you create and configure your App. For those who want to cry out “just come to the point”, no, we need to save the best till last. &lt;/p&gt;  &lt;h4&gt;Step 1: Go to this URL&lt;/h4&gt;  &lt;p&gt;&lt;a href=&quot;https://developers.facebook.com/apps&quot;&gt;https://developers.facebook.com/apps&lt;/a&gt; &lt;/p&gt;  &lt;h4&gt;Step 2: Create an App&lt;/h4&gt;  &lt;p&gt;Give it a display name and name space. The name space will be used to form the URL to access this App which means it should be unique. &lt;/p&gt;  &lt;p&gt;Once the App is created, an App ID and App Secret will be generated. Together, they identify and validate a Facebook App. When you use Facebook .NET APIs (e.g. FacebookClient class in the above example), these two values must be set in the web.config of your site. &lt;/p&gt;  &lt;h4&gt;Step 3: Configure the basic settings of the App&lt;/h4&gt;  &lt;p&gt;&lt;a href=&quot;/link/5e309d7c357a45fbba642323ea8101f1.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/link/60174535e3f84b9fb73522231d6a387b.png&quot; width=&quot;528&quot; height=&quot;495&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;App Domain and Site URL: You need to make sure these use your website domain name as this establishes the link between the Facebook App and your website. My habit is to do all development on my local machine first, so in this case I use alloy.local as the App domain. &lt;/p&gt;  &lt;p&gt;We need to make sure “App on Facebook” is checked. The value of the Canvas URL is a CMS page you want to promote, and that page should contain some personalised blocks only visible to the “event attendees” visitor group you set up. What it means is that when you access the App page (&lt;a href=&quot;http://apps.facebook.com/alloylocal&quot;&gt;http://apps.facebook.com/alloylocal&lt;/a&gt;), the Canvas URL will be loaded into an IFRAME. &lt;/p&gt;  &lt;h4&gt;Step 4: Configure Auth Dialog&lt;/h4&gt;  &lt;p&gt;&lt;a href=&quot;/link/2f9a4e7ddbc747be9d9384f6e1e691bc.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/link/602e50482acc4e30aa576af135d3c596.png&quot; width=&quot;535&quot; height=&quot;312&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;These settings such as an explanation for permissions will be displayed to the user when your Facebook App is seeking user’s approval to access their profile. &lt;/p&gt;  &lt;h4&gt;Step 5: Advanced settings&lt;/h4&gt;  &lt;p&gt;Two settings in this section can be considered. First one is that you can mark your App to run in a Sandbox mode so that only yourself as an App developer will be able to use it. This is useful when you are still at the stage of developing and/or testing your App and do not want the general public to access the App. Second setting is the Canvas Width and Height. You can either set a fix width, which means the width of the IFRAME will be fixed, or set to fluid which means the width of the IFRAME will be dynamic depending on the width of its source. In the screenshot of Part I of this article, you can see I set the canvas width to fluid, and as the width of the AlloyTech site is quite wide, so the IFRAME ended up taking the most part of the entire screen. &lt;/p&gt;  &lt;h4&gt;Step 6: Create test users&lt;/h4&gt;  &lt;p&gt;Earlier this year Facebook introduced a user interface to create test users. Very useful as you do not want to go through the tedious process creating a bunch of real Facebook users (just think about how many new email addresses you have to register!) &lt;/p&gt;  &lt;p&gt;The Roles section of your Facebook App is where to configure test users. It would be good to create at least a couple, one of which will be giving permission to this Facebook App to access its user profile, and the other one won’t. See the screenshot: &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/641d71b404b349319a1981611937ab39.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/link/075506315de54095b6bb9e233a79ad8d.png&quot; width=&quot;556&quot; height=&quot;326&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align=&quot;center&quot;&gt;Add test users &lt;/p&gt;  &lt;p&gt;From this screen, you can switch to the test user, or you can to select “modify” of the above screen to load the following screen to do it there. This modify screen also gives you options to make test users friends, add test user to other Apps and remove the test users. It also gives you a link to display the access token if this test user has authorised the App when you created it, which again, needs more discussions in the next few minutes. &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/159c1962f2904cffb182af3446b8405f.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;image&quot; border=&quot;0&quot; alt=&quot;image&quot; src=&quot;/link/158ea9d35431453094d4e3ab4e72a6d0.png&quot; width=&quot;507&quot; height=&quot;157&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p align=&quot;center&quot;&gt;Modify Test Users &lt;/p&gt;  &lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h3&gt;User Access Token&lt;/h3&gt;  &lt;p&gt;Although Facebook is renowned not treating people’s privacy seriously, there is still one thing it must do – that is, get user’s permission when a third party App tries to access its profile. For this reason, an extra step must be carried out by web developers, that is, load the auth dialog and get the access token. Then the access token can be used in Facebook .NET API to get user’s profile. &lt;/p&gt;  &lt;p&gt;Let’s see how it’s done in code &lt;/p&gt;  &lt;p&gt;string[] extendedPermissions = new[] { &amp;quot;offline_access&amp;quot;, &amp;quot;user_events&amp;quot; }; &lt;/p&gt;  &lt;p&gt;var oauth = new FacebookOAuthClient { AppId = &amp;quot;288150991224591&amp;quot;, RedirectUri = new Uri(&amp;quot;http://alloy.local/&amp;quot;) }; &lt;/p&gt;  &lt;p&gt;var parameters = new Dictionary&amp;lt;string, object&amp;gt;    &lt;br /&gt;{     &lt;br /&gt;{ &amp;quot;response_type&amp;quot;, &amp;quot;token&amp;quot; }     &lt;br /&gt;};     &lt;br /&gt;if (extendedPermissions != null &amp;amp;&amp;amp; extendedPermissions.Length &amp;gt; 0)     &lt;br /&gt;{     &lt;br /&gt;var scope = new StringBuilder();     &lt;br /&gt;scope.Append(string.Join(&amp;quot;,&amp;quot;, extendedPermissions));     &lt;br /&gt;parameters[&amp;quot;scope&amp;quot;] = scope.ToString();     &lt;br /&gt;}     &lt;br /&gt;Response.Redirect(oauth.GetLoginUrl(parameters).ToString());&lt;/p&gt;  &lt;p&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;In this Facebook Event Criteria, we have two types of Facebook users. One is the user created by the marketing department to carry out Facebook marketing activity, which we will have to authorise the App to retrieve a list of its events, and fill in the drop down list (see Part I of this article). The other is the general public, and each individual site visitor needs to authorise the App to access their Facebook event information in order to tell whether they belong to the visitor group. For testing purpose, we also need to authorise the App to access the test user’s profile. &lt;/p&gt;  &lt;h4&gt;To be authorised by the marketing user&lt;/h4&gt;  &lt;p&gt;Using the code example above, the user will be redirected to an URL in the form of &lt;a href=&quot;http://alloy.local/#access_token=AAAABBDFDSFDxxx&quot;&gt;http://alloy.local/#access_token=AAAABBDFDSFDxxx&lt;/a&gt;. Copy the access token value from the browser’s address bar, save it for future use (web.config setting) &lt;/p&gt;  &lt;p&gt;One important thing to note here: by default, when a user authorises a Facebook App, it only allows the App to access its basic public information like username, first name, etc. The events information is not included. That is why we will need to pass in an extra parameter “scope” containing the extended permissions. In this case it needs user_events permission, and because this is a trusted user, we want to get the offline_access permission to make the access token long-standing (see Part I of the article). &lt;/p&gt;  &lt;p&gt;For a full list of permissions, go to this reference link: &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://developers.facebook.com/docs/reference/api/permissions/&quot;&gt;http://developers.facebook.com/docs/reference/api/permissions/&lt;/a&gt; &lt;/p&gt;  &lt;h4&gt;To be authorised by the site visitor&lt;/h4&gt;  &lt;p&gt;The same piece of code can be used, but in this case, it is unreasonable to request offline access In fact, if some Facebook App wants that access level from me, I would click “report this app” without thinking, as if I change my mind later it would be pretty hard to de-authorise that App, and worse, that site could store this token in their own database, then it’s like I’m exposed naked. &lt;/p&gt;  &lt;p&gt;For that reason, we only want to get a temporary permission to access the site visitor’s user events information. Just remove offline_access from the extended permission array. &lt;/p&gt;  &lt;p&gt;&lt;b&gt;&lt;font size=&quot;1&quot;&gt;Facebook.aspx&lt;/font&gt;&lt;/b&gt; &lt;/p&gt;  &lt;p&gt;This is an ad hoc web form that can be deployed to the webroot. It will first execute the above code to load the auth dialog for the user, and once the user approves the App, redirect the user to the Facebook App URL (&lt;a href=&quot;http://apps.facebook.com/alloylocal&quot;&gt;http://apps.facebook.com/alloylocal&lt;/a&gt;). A link can be created within CMS to point at this web form (&lt;a href=&quot;http://alloy.local/facebook.aspx&quot;&gt;http://alloy.local/facebook.aspx&lt;/a&gt;). Then if the user has joined the selected event, she should see the personalised blocks within the IFRAME! &lt;/p&gt;  &lt;h4&gt;To be authorised by the test user&lt;/h4&gt;  &lt;p&gt;You have seen how you authorise the app when you create a test user. But again, by default, user events information is not included. Unfortunately you will not be able to log in as the test user from the auth dialog. The only way to log in as the test user is to go to the App, Modify Test User screen to switch to it (see previous screenshot). &lt;/p&gt;  &lt;p&gt;There is an easy workaround I used – firstly you need to switch to the test user (which will log your real user off). Then, keep the session open (do not close your browser) and just open a new tab in the browser, and manually type in the URL of the auth dialog with the extra user_event permission. The format is like this: &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://www.facebook.com/dialog/permissions.request?app_id=288150991224591&amp;amp;display=page&amp;amp;next=http%3A%2F%2Falloy.local&amp;amp;response_type=token&amp;amp;perms=user_events&quot;&gt;http://www.facebook.com/dialog/permissions.request?app_id=288150991224591&amp;amp;display=page&amp;amp;next=http%3A%2F%2Falloy.local&amp;amp;response_type=token&amp;amp;&lt;b&gt;perms=user_events&lt;/b&gt;&lt;/a&gt;&lt;b&gt;&lt;/b&gt; &lt;/p&gt;  &lt;p&gt;Now there you go! &lt;/p&gt;  &lt;p&gt;&amp;#160; &lt;/p&gt;  &lt;h2&gt;Other minor things to consider:&lt;/h2&gt;  &lt;ul&gt;   &lt;li&gt;You can create a Facebook Page for your company and very easily add the Facebook App to your Facebook Page. &lt;/li&gt;    &lt;li&gt;You can go further to enable Mobile Web for your App. When using an IPhone, IPad or Adroid, they can have a better mobile experience. The principal is the same and you can try EPiServer Mobile Pack. &lt;/li&gt;    &lt;li&gt;Multilingal: there is a language file in this solution which needs to be deployed to the lang folder. It is referred by the Model class (FacebookCriterionModel.cs) &lt;/li&gt; &lt;/ul&gt;  &lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:d5a0f7bd-f1d0-49db-a44b-e3a6bb1b70b9&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;p&gt; &lt;a href=&quot;/link/c5e125c3bf9440968afc28045e8bc11d.zip&quot; target=&quot;_blank&quot;&gt;Source code and binary can be downloaded from here&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;  &lt;p&gt;. &lt;/p&gt;  &lt;h2&gt;To Set up and Test:&lt;/h2&gt;  &lt;p&gt;Use EPiServer Deployment Centre to install a module from zip files (select FacebookEventCriterion.zip) &lt;/p&gt;  &lt;p&gt;Create a Facebook app, set up site domain, site URL, canvas URL, and auth dialog settings. The canvas URL should point at a page of the EPiServer site. Once created, APP ID, App Secret, and APP URL will be generated and should be used in the next step. &lt;/p&gt;  &lt;p&gt;Update web.config:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;lt;configSections&amp;gt;&lt;/p&gt;    &lt;p&gt;&amp;lt;section name=&amp;quot;facebookSettings&amp;quot;      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; type=&amp;quot;Facebook.FacebookConfigurationSection&amp;quot; /&amp;gt;&lt;/p&gt;    &lt;p&gt;&amp;lt;/configSections&amp;gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;lt;facebookSettings appId=&amp;quot;Your Facebook APP ID&amp;quot; appSecret=&amp;quot;Your Facebook APP Secret&amp;quot; /&amp;gt;      &lt;br /&gt;&lt;/p&gt;    &lt;p&gt;&amp;#160;&lt;/p&gt;    &lt;p&gt;&amp;lt;appSettings&amp;gt;      &lt;br /&gt;&amp;lt;add key=&amp;quot;FacebookAccessToken&amp;quot; value=&amp;quot;Facebook Permanent Access Token&amp;quot;/&amp;gt;       &lt;br /&gt;&amp;lt;add key=&amp;quot;FacebookAppUrl&amp;quot; value=&amp;quot;Facebook App URL&amp;quot;/&amp;gt;       &lt;br /&gt;&amp;lt;add key=&amp;quot;FacebookPageUrl&amp;quot; value=&amp;quot;http://your.domain/facebook.aspx&amp;quot;/&amp;gt;       &lt;br /&gt;&amp;lt;/appSettings&amp;gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;#160; &lt;/p&gt;    &lt;p&gt;&amp;lt;episerver.shell&amp;gt;      &lt;br /&gt;&amp;lt;protectedModules&amp;gt;       &lt;br /&gt;&amp;lt;add name=&amp;quot;Criteria&amp;quot; resourcePath=&amp;quot;~/&amp;quot;&amp;gt;       &lt;br /&gt;&amp;lt;assemblies&amp;gt;       &lt;br /&gt;&amp;lt;add assembly=&amp;quot;FacebookEventCriterion&amp;quot; /&amp;gt;       &lt;br /&gt;&amp;lt;/assemblies&amp;gt;       &lt;br /&gt;&amp;lt;/add&amp;gt;       &lt;br /&gt;&amp;lt;/protectedModules&amp;gt;       &lt;br /&gt;&amp;lt;/episerver.shell&amp;gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;FacebookAccessToken needs to be generated using Source/GeneratePermanentToken.aspx. This file should not be deployed to the webroot, and should only be used by a developer. Before running, update GeneratePermanentToken.aspx.cs to match the APP ID and Your Site URL specified in the facebook app. &lt;/p&gt;  &lt;p&gt;Create a Visitor Group using Facebook Event Criterion. The events available from the dropdown are all events that the marketer&#39;s Facebook user is attending. This Facebook user is also used to generate the permanent access token in the previous step. &lt;/p&gt;  &lt;p&gt;On the page where the Facebook app&#39;s canvas URL points at, add some content just for the visitor group created in the previous step. &lt;/p&gt;  &lt;p&gt;Create a link at somewhere obvious of the site, linking to http://your.domain/facebook.aspx. This will authenticate the site visitor&#39;s Facebook user, and let the Facebook user authorise your Facebook app to access information of the events she is attending. Then it will redirect the site visitor to the Facebook app to view the personalised content. &lt;/p&gt;  &lt;p&gt;Also, provide a link on the canvas page, linking to the URL of the Facebook event. Once the site visitor&#39;s Facebook user attends that event, she should see something different on the Facebook app!&lt;/p&gt;  &lt;h2&gt;Reference reading &lt;/h2&gt;  &lt;p&gt;Magnus Rahl’s Richer UI for Custom Criteria &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://world.episerver.com/Blogs/Magnus-Rahl/Dates/2011/3/Richer-UI-for-your-custom-Visitor-Groups-criteria/&quot;&gt;http://world.episerver.com/Blogs/Magnus-Rahl/Dates/2011/3/Richer-UI-for-your-custom-Visitor-Groups-criteria/&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Paul Smith’s Custom View for Criteria &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://world.episerver.com/Blogs/Paul-Smith/Dates1/2011/4/Providing-a-custom-view-for-your-Visitor-Group-criteria/&quot;&gt;http://world.episerver.com/Blogs/Paul-Smith/Dates1/2011/4/Providing-a-custom-view-for-your-Visitor-Group-criteria/&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Dan Matthews’ Pulling Facebook Events into EPiServer &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://world.episerver.com/Blogs/Dan-Matthews/Dates/2011/9/Pulling-Facebook-events-into-EPiServer/&quot;&gt;http://world.episerver.com/Blogs/Dan-Matthews/Dates/2011/9/Pulling-Facebook-events-into-EPiServer/&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;EPiServer Tech Notes – Creating Custom Criteria &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://world.episerver.com/Documentation/Items/Tech-Notes/EPiServer-CMS-6/EPiServer-CMS-6-R2/Visitor-Groups-Creating-Custom-Criteria/&quot;&gt;http://world.episerver.com/Documentation/Items/Tech-Notes/EPiServer-CMS-6/EPiServer-CMS-6-R2/Visitor-Groups-Creating-Custom-Criteria/&lt;/a&gt;&lt;/p&gt;</id><updated>2011-12-01T18:20:30.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Facebook Event Attendance Visitor Group Criterion – Part I</title><link href="https://world.optimizely.com/blogs/Hao-Peng/Dates/2011/11/Facebook-Event-Attendance-Visitor-Group-Criterion--Part-I/" /><id>&lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;p&gt;On the #epidayuk event I demonstrated how to create a custom visitor group criterion with a custom Dojo widget and a MVC controller. Since the entire day had a social theme I could not miss the chance to get into Facebook development. On the day, the code was explained to the tech session attendees and download can be enabled by joining a Facebook event. It is totally understandable that some may not want to expose their Facebook credentials, let alone to authorise some Facebook app that was created by a guy they only met once. So as promised in the seminar, and for the general public who may think this is useful, a Facebook Event Attendance Criterion.&lt;/p&gt;  &lt;h2&gt;What it does:&lt;/h2&gt;  &lt;p&gt;The name says it all – A visitor group can be defined to include this criterion, where the marketer can select the event to attend. See screenshot:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/9ee8d8ec8b8642b2afedcdf1e1b44a05.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image002&quot; border=&quot;0&quot; alt=&quot;clip_image002&quot; src=&quot;/link/cea16eb08ed946d69dc04f070ec9fb83.jpg&quot; width=&quot;434&quot; height=&quot;226&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;An editor will be able to create a block of personalised content just visible to this visitor group. See screenshot:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/52075f01b613490c97b6b60444761901.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image004&quot; border=&quot;0&quot; alt=&quot;clip_image004&quot; src=&quot;/link/29a8b3133b7c48049aaa452788f929fc.jpg&quot; width=&quot;436&quot; height=&quot;245&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;If site visitors are attending/have attended a specified event published on Facebook, they belong to the visitor group and personalised content will be displayed. They will need to authorise your website to access their event attendance information on their Facebook profiles. See screenshots:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/516b833e51a54f9b9a470f768afe69ef.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image006&quot; border=&quot;0&quot; alt=&quot;clip_image006&quot; src=&quot;/link/36ba6615aa294ce7a50e01436a437c6d.jpg&quot; width=&quot;440&quot; height=&quot;332&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Step 1 – Authorise Facebook App&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/d35fb545efc34c9b8d2761a216c6db5c.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image008&quot; border=&quot;0&quot; alt=&quot;clip_image008&quot; src=&quot;/link/414c484cc133479da05f8bdaabfa388c.jpg&quot; width=&quot;444&quot; height=&quot;309&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Step 2 - No personalised content yet&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/0f2c3a1c84e341abbe93d730c8ae8dd5.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image010&quot; border=&quot;0&quot; alt=&quot;clip_image010&quot; src=&quot;/link/288afaa960bf480ea44c9fc10d2cfe54.jpg&quot; width=&quot;447&quot; height=&quot;288&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Step 3 - Join the event&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/c8b1cd6ecd714800a27746620660b649.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image012&quot; border=&quot;0&quot; alt=&quot;clip_image012&quot; src=&quot;/link/8c2d82245ac7422e931ba6009076d02f.jpg&quot; width=&quot;449&quot; height=&quot;334&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;Step 4 – personalised content is visible&lt;/p&gt;  &lt;h2&gt;How it does it:&lt;/h2&gt;  &lt;p&gt;The development is formed of two parts – to create a widget for the criteria in the visitor group UI, and to implement the IsMatch method that will be evaluated when a personalised page is visited.&lt;/p&gt;  &lt;h4&gt;Visual Studio Solution&lt;/h4&gt;  &lt;p&gt;Again, a picture equals a thousand words:&lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/86e18947c60642a6aedccff340070262.jpg&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;clip_image014&quot; border=&quot;0&quot; alt=&quot;clip_image014&quot; src=&quot;/link/c8240ec564c14b548c4ad4aba936064e.jpg&quot; width=&quot;242&quot; height=&quot;392&quot; /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;h4&gt;FacebookEventCriterion.cs&lt;/h4&gt;  &lt;p&gt;The main criterion class, inheriting from EPiServer.Personalization.VisitorGroups.CriterionBase&amp;lt;T&amp;gt;, where T is the class of the criterion model (will come to that in a minute). We also want to decorate this class with EPiServer.Personalization.VisitorGroups.VisitorGroupCriterionAttribute in order to set the criterion’s display name, category, etc, and in this example, initialise the Dojo Widget using a piece of Javascript that can be specified in ScriptUrl parameter (will come to that in 2 minutes)&lt;/p&gt;  &lt;p&gt;IsMatch() is the only method to override. In this case, check if the user has authorised the Facebook App and has attended the selected Facebook event (which is accessible through the Model object). &lt;/p&gt;  &lt;h4&gt;FacebookCriterionModel.cs&lt;/h4&gt;  &lt;p&gt;The model class, inheriting from EPiServer.Personalization.VisitorGroups.CriterionModelBase. It contains a public property “EventName” (string) that can be selected from a dropdown list when creating a visitor group. The selected value will then be passed to the IsMatch method in the main criterion class.&lt;/p&gt;  &lt;p&gt;By default, EPiServer will use a text box for a string property when using the criteria to create visitor groups. In this case, we want to use a dropdown list instead, which means the EventName property needs some annotation using EPiServer.Personalization.VisitorGroups.DojoWidgetAttribute. &lt;/p&gt;  &lt;p&gt;e.g. [DojoWidget(WidgetType = &amp;quot;dijit.form.FilteringSelect&amp;quot;, …)]&lt;/p&gt;  &lt;p&gt;This drop down needs to have some options, which is why the FacebookEventCriterion class has used ScriptUrl in its VisitorGroupCriterionAttribute.&lt;/p&gt;  &lt;h4&gt;FacebookEventCriterion.js&lt;/h4&gt;  &lt;p&gt;This is the Javascript that will be executed when dragging and dropping the criterion when creating a visitor group. It will initialise an AJAX call to the URL &lt;a href=&quot;http://domain/criteria/FacebookEventCriterion/GetAllEvents&quot;&gt;http://domain/criteria/FacebookEventCriterion/GetAllEvents&lt;/a&gt;, which is a piece of code running on the server to get all the Facebook events a certain Facebook user has attended (or if you want, created). This Facebook user could be a user created by the marketer or marketing department that organised the actual event, or a user that is used for other Facebook marketing activities. The server code will return a JsonResult object that the Javascript can capture and fill the Dojo FilterSelect Widget (a drop down list) with all the event details.&lt;/p&gt;  &lt;h4&gt;FacebookEventCriterionController.cs&lt;/h4&gt;  &lt;p&gt;This is the fore-mentioned server code to get all the event details. It will use Facebook .NET APIs to firstly get the user authorisation token and use the token to get all the events that this user has attended. It will return a JsonResult object, with the EventName being both the dropdown option’s ID and itsText, so it can be serialised and passed to the client Javascript.&lt;/p&gt;  &lt;h4&gt;GeneratePermanentToken.aspx&lt;/h4&gt;  &lt;p&gt;This is a page that you only need to run once to get a “permanent” (or long standing) access token for your Facebook App to get the Facebook user’s profile events information. We want to get a long standing token because this is likely to be a Facebook user created by the same marketing department that is responsible for the web site. So there isn’t any trust issue here, and this Facebook user is unlikely to change, and the password of this Facebook user is unlikely to change, either. However if any of situation changes, you will need to regenerate the access token. We want to allow this by using an AppSettings section in the web.config.&lt;/p&gt;  &lt;p&gt;In order to generate an access token, you firstly need a Facebook App. That topic, together with the source code download, deployment and configuration, will come in Part II of this article.&lt;/p&gt;</id><updated>2011-11-30T13:03:00.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Another Accessibility Checker</title><link href="https://world.optimizely.com/blogs/Hao-Peng/Dates/2011/10/Another-Accessibility-Checker/" /><id>&lt;h3&gt;&amp;#160;&lt;/h3&gt;  &lt;h3&gt;EPiServer and Accessibility Checker&lt;/h3&gt;  &lt;p&gt;Seems an old topic in the current CMS market. There are many ways of checking the site’s compliance in EPiServer. &lt;a title=&quot;Wave Accessibility Checker&quot; href=&quot;http://labs.episerver.com/en/Blogs/Allan/Dates/2010/7/Checking-a-accessibility-for-a-page-with-Wave/&quot; target=&quot;_blank&quot;&gt;Allan’s post&lt;/a&gt; talked about how to use WAVE to achieve the goal, and &lt;a href=&quot;http://www.episerver.com/en/Extras/Licenses/EPiMore/EditLive!-for-EPiServer/&quot; target=&quot;_blank&quot;&gt;EditLive&lt;/a&gt; provides a rich editor that checks the compliance while the editor is typing. I thought it would be good to provide yet another alternative open source solution so the control is completely yours and it is free. &lt;/p&gt;  &lt;p&gt;It is called AChecker, an open source project hosted by &lt;em&gt;Adaptive Technology Resource Center&lt;/em&gt; at the &lt;em&gt;University Of Toronto&lt;/em&gt; (see &lt;a href=&quot;http://atutor.ca/achecker/&quot; target=&quot;_blank&quot;&gt;project page&lt;/a&gt;). Currently it checks your web page against WCAG1, WCAG2, Section 508 (US), BITV (Germany) and Stanca Act (Italy). It is written in PHP/MySQL as an open source project, which means you can download it, set it up, and use it locally on your server. If PHP is not your plate of food, you can always convert it to .NET. &lt;/p&gt;  &lt;h1&gt;&amp;#160;&lt;/h1&gt;  &lt;h3&gt;Features and why it is different:&lt;/h3&gt;  &lt;ul&gt;   &lt;li&gt;Compliance selection &lt;/li&gt;    &lt;li&gt;Multi-lingual support &lt;/li&gt;    &lt;li&gt;Guideline creation and customisation &lt;/li&gt;    &lt;li&gt;Decision making for warnings (checks that machines are not clever enough to perform) &lt;/li&gt;    &lt;li&gt;TinyMCE Plug-in &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;For more details, check out these pages: &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://www.tinymce.com/wiki.php/Accessability&quot;&gt;http://www.tinymce.com/wiki.php/Accessability&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://atutor.ca/achecker/&quot;&gt;http://atutor.ca/achecker/&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Here is the URL pointing to a little open source CMS (ATutor) that show how an editor interface could be integrated with AChecker. &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;http://atutor.ca/atutor/demo.php&quot;&gt;http://atutor.ca/atutor/demo.php&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Fortunately if you are not ready to do the local install, AChecker also provides a URL that can take HTML as input through POST request, and return the errors and warnings to you. Better still, it has a ready to use TinyMCE plug-in that you can take and plug straight into your EPiServer editor. This probably is exactly what editors need as they only need to care about the content they are responsible for instead of the entire page.&lt;/p&gt;  &lt;p&gt;&amp;#160; &lt;/p&gt;  &lt;h3&gt;Integration with EPiServer&lt;/h3&gt;  &lt;p&gt;This is what I tried as the first step. The following screenshots shows the idea &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/0dda126ce8824708adc193c99e90b582.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;tinymce-admin&quot; border=&quot;0&quot; alt=&quot;tinymce-admin&quot; src=&quot;/link/89f81d118860424b95100c07ca2da3eb.png&quot; width=&quot;316&quot; height=&quot;234&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160; &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/da3cb39fbcf84ec59fc2bac25f786b32.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;tinymce-edit&quot; border=&quot;0&quot; alt=&quot;tinymce-edit&quot; src=&quot;/link/5354bf87e2aa4ab18bc6c4eb9ebbb899.png&quot; width=&quot;321&quot; height=&quot;192&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href=&quot;/link/1b35a31cf1bb4a56bad5dc3a46e88ab1.png&quot;&gt;&lt;img style=&quot;background-image: none; border-right-width: 0px; padding-left: 0px; padding-right: 0px; display: inline; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px; padding-top: 0px&quot; title=&quot;achecker.ca&quot; border=&quot;0&quot; alt=&quot;achecker.ca&quot; src=&quot;/link/fac7495169754a358c2475d6171f1736.png&quot; width=&quot;317&quot; height=&quot;235&quot; /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;h3&gt;Next Steps&lt;/h3&gt;  &lt;p&gt;As you can see by now, using the URL and posting HTML to it may not be ideal for editors who normally do not understand those errors and warnings in the context of the HTML source. If you need to take a step further because of this, you will have two options:&lt;/p&gt;  &lt;p&gt;a) Although I have not tried myself, you could utilise AChecker Web Service APIs &lt;a href=&quot;http://achecker.ca/documentation/web_service_api.php&quot; target=&quot;_blank&quot;&gt;documented here&lt;/a&gt; to pass in the HTML, analyse the returned message and highlight the corresponding text within the TinyMCE editor or in preview mode&lt;/p&gt;  &lt;p&gt;Or &lt;/p&gt;  &lt;p&gt;b) Forget about the on-line service. Download everything and install the checker locally. You can remove user interface provided by the application and just convert the checker engine to .NET (we have done that for a former version of AChecker in my previous job and it took 1 man 2 weeks), then the control is all yours how you want to integrate with EPiServer.&lt;/p&gt;</id><updated>2011-10-13T11:54:37.0000000Z</updated><summary type="html">Blog post</summary></entry> <entry><title>Weather Criterion</title><link href="https://world.optimizely.com/blogs/Hao-Peng/Dates/2011/8/Weather-Criterion/" /><id>&lt;p&gt;Apparently British people talk about weather a lot. So wouldn’t it be good to personalise the content based on the weather of the visitor’s location?&amp;#160; Your site visitor had a bad day before visiting your site, and found out that at least it is still sunny outside and he can go to the beach with the family after work &lt;img style=&quot;border-bottom-style: none; border-left-style: none; border-top-style: none; border-right-style: none&quot; class=&quot;wlEmoticon wlEmoticon-smile&quot; alt=&quot;Smile&quot; src=&quot;/link/7495bb5aa6b1459b91e8dfdcc6cf1c2e.png&quot; /&gt;&lt;/p&gt;  &lt;p&gt;The Custom Criterion uses Google Weather API and expect the user profile to have a ZipCode property. If you are trying it on the Alloy Tech site, set up the workroom component, and locate the file ~/templates/AlloyTech/Units/Placeable/PersonalSettings.ascx. You can easily modify the code to set/get user’s ZipCode information.&lt;/p&gt;  &lt;p&gt;A typical zip code in UK, Sweden and USA is such as&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;EC1N 8SS &lt;/li&gt;    &lt;li&gt;103 86, Stockholm &lt;/li&gt;    &lt;li&gt;60181 &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Very quick and dirty project as part of my new exposure to EPiServer personalisation. Now you have the source code so let’s see your imaginations!&lt;/p&gt;  &lt;div style=&quot;padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px&quot; id=&quot;scid:fb3a1972-4489-4e52-abe7-25a00bb07fdf:be848404-4e3a-4805-a7fb-2f9396d0f82a&quot; class=&quot;wlWriterEditableSmartContent&quot;&gt;&lt;p&gt;See the code: &lt;a href=&quot;/link/b3cd30a922af46459b162e8e972910a0.zip&quot; target=&quot;_blank&quot;&gt;Download&lt;/a&gt;&lt;/p&gt;&lt;/div&gt; .    </id><updated>2011-08-01T15:09:00.0000000Z</updated><summary type="html">Blog post</summary></entry></feed>