Friday, March 26, 2010

YouTube "Source of Views" definitions


Recently was asked what the View's types in YouTube's Insights tool mean. Shows up in tables as "Source of Views". I did some searching and couldn't find any simple list or definitions.

Did some digging and here's the results of my analysis.

Source TypeDefinition

Embedded Player
embedded player view on another site
YouTube Channel Page Player player on channel page - featured video
Youtube Other played on youtube directly from navigating to page
Advertising played for advertisment on youtube
Related Video Showed up as related video to another video and was played
Mobile Devices played on mobile device player
External Linksexternal site linking directly to video player page
Viral/Other No referrer - direct navigation to video
YouTube Search found via youtube search
Google Search found via google search
Google Video Search found via google video search
Subscriber played within my account/subscriptions module
Promoted Featured video

From the all videos' view you can drill down to a specific video, and from there go to the "Discovery" section for that video. Once looking at "Discovery" for a specific video these headings allow you to drill down and see the exact sites that were creating the traffic.



Update
Since this was originally posted, YouTube has updated Insight. Here's what you now see in YouTube:
YouTube View Types Screenshot

Saturday, February 06, 2010

Embeding Flash in Facebook Dialog box

UPDATE: Some of the techniques below are no longer working in Facebook. Please find an updated technique here: Updated: Embeding Flash in Facebook Dialog Box

Ran into more work than I expected on this, and didn't find much in the way of resources out there to help.

Here's the scenario: on a Facebook page tab (profile tab) want to have links that open a dialog box with a youtube video. In my case its a nice image map (css driven) of images that open the video the image represents.

Primary challenges:
fb:swf fbml must be used. Actually there is now a createFBMLObject() in FBJS and the only object it will create is fb:swf but its in beta and there isn't much documentation yet.

Attempt #1:
After much research and trial and error I got this as a workable solution:
use fb:dialog with the fb:swf as the content block
<a title="Pop up video" href="#"  clicktoshowdialog="tubeIt1"></a>
<fb:dialog id="tubeIt1" cancel-button="true">
<fb:dialog-title>Luxury</fb:dialog-title> 
<fb:dialog-content>
<fb:swf 
swfsrc='http://www.youtube.com/v/PQHPYelqr0E&hl=en_US&fs=1&'
imgsrc='http://www.someurl.com/static/images/PorkAndBeans.jpg' 
width='430' height='295' />
<span>Pork and beans!</span>
</fb:dialog-content>
<fb:dialog-button type="button" value="close" close_dialog="true" /> 
</fb:dialog>



This solution works well enough and is easy, however it introduces a problem - if a user opens the dialog, then closes it, then opens it again the video can no longer be played (the static image is not clickable).

Final solution:
Final solution I landed on was to have fbjs create the dialog and just store the fb:swf in a fb:js-string. This removes the need to click through the static image to play the flash in the dialog box.
However it didn't work the second time the dialog was opened as the flash had already been injected. The workaround to that turned out to be replacing a marker in the dialog with the fb:js-string variable.

Here it is:
<script language="javascript">
var dialogCounter = 0;
var dialogActive;


function showVideo(title, video) {
if(dialogCounter > 0)  return false; //don't allow more than one instance of this dialog
else {

dialogCounter += 1;

dialogActive = new Dialog();

dialogActive.showMessage(title + dialogCounter, dialogText); 

dialogActive.onconfirm = function() { dialogCounter = 0; }

document.getElementById('dialog_content').setInnerFBML(video);

return false;

}
}



</script>

<fb:js-string var="dialogText">   
<div id="dialog_content">
Marker to be replaced
</div>  
</fb:js-string> 

<a title="Pork and Beans" href="#" onclick="return showVideo('Pork and Beans', tubeIt1)"></a>

<fb:js-string var="tubeIt1">
<fb:swf 
swfsrc='http://www.youtube.com/v/PQHPYelqr0E&hl=en_US&fs=1&'
imgsrc='http://www.someurl.com/static/images/PorkandBeans.jpg' 
width='430' height='295' />
<span>Pork and Beans!</span>
</fb:js-string>


The other annoyance was that the dialogs stack on each other causing the user to have to "ok" each one individually if they open more than one. Introducing the dialogCounter variable prevents any new dialogs from being opened if one is already open.

Hope this saves someone else some time!

Thursday, July 30, 2009

404 2 error - ASP pages result in Page Not Found

Hit an odd one today. A colleague of mine was struggling to restore an old classic ASP app to a dev server and was IIS was returning "Page not found" for any .asp file. Static files, and even aspx files were fine but asp was not.

Checked the path to the asp.dll and the permissions (scripts enabled, IIS user has access) to no avail.

Finally dug into the IIS log and found out the 402 error had a substatus of 2.

Turns out that this error means the web service extension is locked down. (Thanks to Manish Pansiniya's post).

Here's what to look for in IIS:

Sunday, July 26, 2009

Automatically determine if there is any data loss when navigating away from a page.

Recently found a situation where a client was looking to ensure people didn't accidentally navigate away from a page when entering data on a website.

This isn't normally that difficult, except in this case we didn't control much of the page content (dynamically pulling content).

I came up with this approach in jQuery I thought it would be worth sharing. The approach is:
- bind all ":input" items with a onchange event (this will catch all form elements)
- onchange of an input add a marker css class to flag that it was modified
- bind to the form submit event, remove all markers on the form when submitted
- onbeforeunload look see if there are any markers on the page, if there is warn the user the data will be lost

This approach works with multiple forms on the page. Note the traditional javascript event use onbeforeunload - jQuery's beforeunload event will now allow the user to cancel unloading the page.

Next iteration of this type of approach will extend it to throw up an overlay with a listing of what form elements have data changes, and allow the user to post submits via ajax.

Here's the code:
<script type="text/javascript">

$(document).ready(function() {
$(':input').change(function() { $(this).addClass('elementHasChanged'); });
$("form").submit(function() {
//if the eventing item is part of a form, remove all the change flags from
$(this).children('.elementHasChanged:input').removeClass('elementHasChanged');
});
});

window.onbeforeunload = function() {
var changedCount = $('.elementHasChanged:input').length;
if (changedCount > 0) { return "Any changes you have made will be lost"; }

}
</script>

Update: Here's a working sample

Sunday, July 12, 2009

YouTube Channel on a Facebook profile page .NET

After searching through many YouTube apps on Facebook I couldn't find one that did what I wanted - which was to display the videos from a specific channel on YouTube. They all offered me the ability to manually specify the videos but I want to be lazy and dynamically suck them in from the channel.

To do this either as an iframe based app, or FBML driven profile tab isn't to difficult and doesn't require the Facebook API. I did leverage the Google .NET Client API though.

Here's the steps in overview:
  1. Identify the Channel name you want: ex FlightOfThConchords
  2. Build the URL for the YouTube call (reference)
  3. Make the request to YouTube
  4. Iterate the results into a data object you want to work with
  5. Iterate relevate sub objects off the return set from YouTube (MediaThumbnails and MediaContents in my case)
  6. Thrown the results to the page for turning into elements
  7. If doing an IFRAME app, then use the object tag, if doing FBML do FB:SWF (see previous post)
Keep reading for more detail.



I'm using ASP.NET MVC so here's my solution:


First I enjoy light weight model objects - so I define my objects I'll pass around:


public class YouTubeVideosCollection : System.Collections.Generic.List<YouTubeVideo>
{
}
public class YouTubeVideo
{
public string Blob;
public string Title;
public string Status;
public string Content;
public System.Collections.Generic.List<YouTubeVideoThumbnail> ThumbNailList = new System.Collections.Generic.List<YouTubeVideoThumbnail>();
public System.Collections.Generic.List<YouTubeVideoMediaType> MediaList = new System.Collections.Generic.List<YouTubeVideoMediaType>();
}
public class YouTubeVideoMediaType
{
public string Url;
public string Format;
public string Duration;
}
public class YouTubeVideoThumbnail
{
public string Url;
public string Width;
public string Height;
}

There's no logic or api in those so no special includes needed.



I then build out a provider class that will do the heavy lifting and return my YouTubeVideosCollection object. I head over to Google to register for an application id (app_key, app_name).


public static class YouTubeAppProvider
{
public static YouTubeVideosCollection RetrieveYouTubeChannelVideos() {
//I didn't implement paging yet, but this worker class is ready for it
//this default call requests the first 11 videos starting at index 1
return RetrieveYouTubeChannelVideos("1","11");
}
public static YouTubeVideosCollection RetrieveYouTubeChannelVideos(string indexStartAt, string maxResults)
{
//more info on query string params at: http://code.google.com/apis/youtube/2.0/developers_guide_protocol_api_query_parameters.html#qsp
//get app_id and app_key from google API Parter dashboard
Google.YouTube.YouTubeRequestSettings settings = new Google.YouTube.YouTubeRequestSettings("My App Name", app_id, app_key);
Google.YouTube.YouTubeRequest request = new Google.YouTube.YouTubeRequest(settings);

Uri youtubeChannel = new Uri("http://gdata.youtube.com/feeds/api/users/FlightOfThConchords/uploads?start-index=" + indexStartAt + "&max-results=" + maxResults);
Google.GData.Client.Feed<google.youtube.video> feed = request.Get<google.youtube.video>(youtubeChannel);

YouTubeVideosCollection vids = new YouTubeVideosCollection();
foreach (Google.YouTube.Video entry in feed.Entries)
{
YouTubeVideo vid = new YouTubeVideo();
vid.Title = entry.Title ;


vid.Content = entry.Content;
foreach (Google.GData.Extensions.MediaRss.MediaThumbnail thumb in entry.Thumbnails) {
YouTubeVideoThumbnail thumbnail = new YouTubeVideoThumbnail();
thumbnail.Url = thumb.Url;
thumbnail.Width = thumb.Width;
thumbnail.Height = thumb.Height;

vid.ThumbNailList.Add(thumbnail);

}
foreach (Google.GData.YouTube.MediaContent mediaContent in entry.Contents ) {
//formats: http://code.google.com/apis/youtube/2.0/reference.html#formatsp
//I only want the Format 5 - which is the embedable version
if (mediaContent.Format.Equals("5"))
{
YouTubeVideoMediaType media = new YouTubeVideoMediaType();
media.Duration = mediaContent.Duration;
media.Format = mediaContent.Format;
media.Url = mediaContent.Url;
vid.MediaList.Add(media);
}
}
vids.Add(vid);
}
return vids;
}
}

This class will need the following:
  • Google.GData.Client

  • Google.GData.Extensions.MediaRss

  • Google.YouTube

You get these from the Google .NET Client API



In my controller I define a method to invoke the worker.


public ActionResult Channel()
{
ViewData.Model = SampleBox.Models.YouTubeAppProvider.RetrieveYouTubeChannelVideos();

return View();
}



Lastly I define the view, which is able to be strongly typed off the YouTubeVideosCollection we defined earlier. This first set of code will run in as an independent page (or within an IFRAME as a Facebook App).


<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<SampleBox.Models.YouTubeVideosCollection>" %>

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Channel
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

<h2>Channel</h2>

<div class="videoCollection">
<ul>
<%
SampleBox.Models.YouTubeVideosCollection videos = ViewData.Model;
bool first = true;
string width = "425";
string height = "350";
foreach (SampleBox.Models.YouTubeVideo vid in videos)
{
if (first)
{%>
<li class="first">
<% } else { %>
<li>
<% } %>
<% foreach (SampleBox.Models.YouTubeVideoMediaType media in vid.MediaList)
{ %>
<%= vid.Title %><br />
<object width="<%=width%>" height="<%=height %>">
<embed src="<%= media.Url %>"
type="application/x-shockwave-flash" wmode="transparent"
width="<%=width %>" height="<%=height %>">
</embed>
</object>

<% } %>
</li>
<%
first = false;
width = "215";
height = "175";
} %>
</ul>
</div>
</asp:Content>



This second example will work within the context of a facebook profile tab - note there is no master page to inherit from and no html/body tags, and the style has been defined inline intentionally.

<%@ Page Title="" Language="C#" Inherits="System.Web.Mvc.ViewPage<SampleBox.Models.YouTubeVideosCollection>" %>


<h2>Channel</h2>
<style type="text/css">
.videoCollection ul
{
border-bottom: 1px #5C87B2 solid;
padding: 0 0 2px;
position: relative;
margin: 0;
width: inherit;
text-align: center;
}

.videoCollection ul li
{
list-style: none;
display:inline-block;
width: 340px;
height: 215px;
border: solid 1px black;
overflow: hidden;
position: static;
}
.videoCollection ul li.first
{
width: 690px;
height: 375px;
display: block;
clear: both;
vertical-align: middle;
}

.videoCollection {
width:690px;
border: solid 1px black;
}
</style>
<div class="videoCollection">
<ul>
<%
SampleBox.Models.YouTubeVideosCollection videos = ViewData.Model;
bool first = true;
string width = "425";
string height = "350";
foreach (SampleBox.Models.YouTubeVideo vid in videos)
{

if (first)
{%>
<li class="first">
<% } else { %>
<li>
<% } %>
<% foreach (SampleBox.Models.YouTubeVideoMediaType media in vid.MediaList)
{ %>
<%= vid.Title %><br />
<fb:swf
imgsrc="<%= vid.ThumbNailList[0].Url %>"
swfsrc="<%= media.Url %>"
height="<%=height%>"
width="<%=width%>"
/>


<% } %>
</li>
<%
first = false;
width = "215";
height = "175";
} %>
</ul>
</div>

There's lots of refactoring and error handling yet to do, but this is a solid reference point to share - hope its useful for you.

Facebook Profile Page (Tab on a Business Page)

Been playing with Facebook a bit recently and thought I'd summarize a few points I've learned:
  1. Tabs on business pages are called "Profile Tabs" in Facebook parlance.
  2. Tabs are actually a setting off of an application (so you'll need a very simple application)
  3. The URL to the tab content must be relative to the main URL (Canvas) of the simple application
  4. Tabs are limited in functionality - they are markup only (no iframes) and a subset of FBML.
  5. Inline CSS and Javascript only.
  6. Flash can be used, but cannot be viewed until a user clicks the element (fb:swf)
  7. Make sure you specify an image src on the fb:swf tag - otherwise there is nothing for the user to click on to start the flash
  8. For some reason .htm/.html files wouldn't work for me, though .aspx was fine.
  9. Images will be cached by Facebook (so throw a query string on if you want to force them to change).

Friday, March 20, 2009

Mix09

Checking out some of the new technologies coming out at Mix this year – as always very exciting stuff.

(VisitMix.com)

ASP.NET MVC 1.0

Super Preview – view web pages you are building in multiple browsers (via the cloud) – built into Expression Web 3.0

Web Platform Installer – make it easy to get the latest “bits”

I’m really interested and excited on all of these.