denverfoundation / storybase

The code behind Floodlight
http://floodlightproject.org
MIT License
11 stars 7 forks source link

Wire in home page banner (user story #302) #198

Closed patternleaf closed 11 years ago

patternleaf commented 12 years ago

need live images, titles, and links.

User story number 302

jwirfs-brock commented 12 years ago

@patternleaf Is this something you think we could do for launch, time- and effort-wise?

patternleaf commented 12 years ago

the template code should more or less be ready for it. i'm not sure offhand where we left the wiring. @ghing, are there any major obstacles to wiring this up that you know of? was this on my plate to finish?

ghing commented 12 years ago

@jwirfs-brock, @patternleaf I think the biggest issue that this is still blocked on is deciding how stories will be selected for this region. Should this be curated, or random? Personally, I feel like it might be better to hold off on this until a wider number of stories is available.

jwirfs-brock commented 12 years ago

How many stories go into the banner? Right now we have more than 50 on staging, and will be adding a bunch in the next week.

I suggest the banner either shows the x more recently added stories or a random selection. I prefer random, because they are shown most recent first on the explore page. On Oct 26, 2012 7:28 AM, "Geoffrey Hing" notifications@github.com wrote:

@jwirfs-brock https://github.com/jwirfs-brock, @patternleafhttps://github.com/patternleafI think the biggest issue that this is still blocked on is deciding how stories will be selected for this region. Should this be curated, or random? Personally, I feel like it might be better to hold off on this until a wider number of stories is available.

— Reply to this email directly or view it on GitHubhttps://github.com/PitonFoundation/atlas/issues/198#issuecomment-9812773.

ghing commented 12 years ago

Just a quick note, I think that it might be kind of computationally expensive to render this straight from the database with each page load. I want to do some profiling of this before we roll it out to ensure snappy loading of the home page which I think is really important. I won't be able to do this before Thursday, but can make this a priority for soon after.

jwirfs-brock commented 12 years ago

That sounds good -- I'd rather have the banner working quickly and efficiently.

wendynorris commented 11 years ago

Revisiting a question @ghing asked earlier in this thread:

Should the banner be automated or curated? What are the technical implications? What are the marketing implications? Is it all or nothing? Does the admin have the ability to turn off/reactivate automation for other needs?

ghing commented 11 years ago

This is a brain dump of implementation ideas/questions. @patternleaf, can you take a look at this and then maybe we can discuss via chat:

Should the banner be loaded with the Homepage view, or asynchronously with JavaScript (or both)?

Does anyone have any examples of this kind of banner in the wild to see their behavior?

How should this be included in the homepage template?

I was thinking the best way to implement this might be a template tag:

{% story_banner %}

or

{% story_banner "strategy_name" %}

Right now it's implemented as a Django CMS plugin in cmsplugin_storybase.cms_plugins.HomepageBannerPlugin which uses the template homepage_banner_plugin.html for rendering. storybase_story.views.homepage_banner_list populates the stories list and currently just returns dummy information.

I think it makes sense to make this a template tag instead of a plugin because it makes it more CMS agnostic and there's really only one place we'd want the banner to show up.

What strategies should be used for generating banners?

I'm thinking of making a BannerStrategy class that encapsulates various ways of selecting the stories to be included in the banner.

Ideas I had for strategies:

I think random should be the first one we implement.

How we render the banner in the background?

Since it has to hit the database/cache a number of times, or at least do some fairly complex joins, to get the stories for the banner, it seems like it makes sense to pre-render the banner.

My thought was to use celery to handle the async task queue, and this Stack Overflow post suggests a strategy along these same lines.

But that still leaves the question, what should trigger the task to pre-render the banner? Should it run periodically, or should each visitor trigger the render for the next visitor?

Do we want to track any events with this?

We can wire in some analytics hooks to see if the banner is successful in getting users to click on stories.

Should this be done based on user interactions (click event handlers on the banner links that log Google Analytics Events) or via the request (via a querystring parameter, e.g. /stories/STORY-SLUG/?source=banner). Is there a way for Google Analytics to automatically check this? I feel like if we check this via querystring parameter, we should still log things server-side to Google Analytics as opposed to the database. Since I'll likely already use celery, we should be able to do this asynchronously.

It looks like Google Analytics can track these via specific query string parameters using a feature called custom campaigns

patternleaf commented 11 years ago

@ghing some initial thoughts:

How should this be included in the homepage template?

Agreed that a template tag makes more sense than a CMS plugin.

Should the banner be loaded with the Homepage view, or asynchronously with JavaScript (or both)?

How we render the banner in the background?

Are these both aimed at addressing the time required to calculate the stories? Or are they addressing different problems? In other words: would an asynch javascript solution be instead of a celery-based solution?

Should it run periodically, or should each visitor trigger the render for the next visitor?

The latter seems to make sense so long as the cache is always guaranteed to have some banner view, even if it's stale (and as long as we don't really care too much if that happens once in a while).

Any ideas on the actual time it would take to generate a banner view? We're still talking a matter of maybe tens or hundreds of milliseconds, right?

Question for edge case: What happens if a cached view refers to a story that has since been deleted? Maybe story additions/deletions/changes should trigger a banner recalculation?

ghing commented 11 years ago

@patternleaf,

Are these both aimed at addressing the time required to calculate the stories? Or are they addressing different problems? In other words: would an asynch javascript solution be instead of a celery-based solution?

I think the Celery-based solution is the way to go, but that adding async JavaScript might be some nice extra polish. In addition to loading the stories and their image paths from the database, there's also the time it will take to load all the images. I was just thinking that an async JavaScript solution could be used so that the banner is only displayed when it's completely rendered (including image loading), or that the elements could be populated as they come in in a more controlled fashion. I would add this at the end of the implementation though and don't think it's crucial.

Any ideas on the actual time it would take to generate a banner view?

Not yet. As we speak, I'm working on a first pass at this with no caching just to see how long it takes. The flexibility we gain in terms of data storage with translations and polymorphic asset types makes for a bit of a performance penalty when retrieving lots of stories. I opted to cache because some of the use cases still seem in flux enough to not flatten out the data model or writing custom Managers or QuerySet implementations that minimize the number of queries and instead just cache things like this.

Question for edge case: What happens if a cached view refers to a story that has since been deleted? Maybe story additions/deletions/changes should trigger a banner recalculation?

Yup. This is what I do for the caching I used to speed up the Explore page loading. The cached story metadata gets invalidated and recalculated when it's topics/places/etc change.

ghing commented 11 years ago

I implemented a first pass at this with no background generation and no caching. The performance seems pretty ok, actually, maybe because I'm already caching the featured image URL to speed up the explore view. I'm going to do some more systematic profiling to compare the homepage load times with and without the banner.

ghing commented 11 years ago

@jwirfs-brock I'm assigning this to you because I want to know:

jwirfs-brock commented 11 years ago

@ghing Here are my thoughts on your questions:

ghing commented 11 years ago

Note to self: I don't want to go to far down the rabbit hole of Google Analytics and A/B testing, but I wanted to capture a few thoughts from my reading:

Decision: Put in campaign URL parameters so we can track how many users visit stories via different banner implementations but don't try to implement routing for doing experiments.

wendynorris commented 11 years ago

Sounds good to me, Geoff.

With such a small user/reader base currently, I'm not sure we'd get terribly valid results with A/B testing or GA Experiments yet. The other consideration is what precisely are we trying to test/track? I think I'll have some better ideas to draft some test hypotheses once I dive into the latest survey results that are due today.

How's that?

Wendy

** wendy norris http://about.me/wendynorris ceo + founder :: tekhne media, inc a digital information and media collective 720 281 9378 :: mobile

* http://about.me/wendynorris *

On Fri, Feb 15, 2013 at 9:42 AM, Geoffrey Hing notifications@github.comwrote:

Note to self: I don't want to go to far down the rabbit hole of Google Analytics and A/B testing, but I wanted to capture a few thoughts from my reading:

  • The StackOverflow question Any thoughts on A/B testing in Django based project?http://stackoverflow.com/questions/752919/any-thoughts-on-a-b-testing-in-django-based-projectpost has some good ideas for A/B testing in Django apps as well as some links to repos
  • I had originally thought of using Google Analytics "Campaigns" for tracking the effectiveness of different banner strategies, but it looks like there are also "Experiments". The experiments have to be explicitly set up, with specific variations defined (with different URLs) and tracking code inserted for each experiment. I don't know if it's worthwhile to set this all up and I'm not sure of the best way to put hooks in to set this up without hard-coding our experiments into the views/templates of our code base.
  • I shouldn't get too hung up with implementing code for displaying random banners in the banner implementation. It seems like we'll want to have some higher-level mechanism for showing different content to different users.

Decision: Put in campaign URL parameters so we can track how many users visit stories via different banner implementations but don't try to implement routing for doing experiments.

— Reply to this email directly or view it on GitHubhttps://github.com/PitonFoundation/atlas/issues/198#issuecomment-13615399.

ghing commented 11 years ago

I did some simple testing of page load times using ConfessJs

I loaded the homepage 25 times for each method of selecting stories for the banner. These are the results:

Banner Type Average Load Time (ms)
No Banner 2214
Topic (Arts and Culture) 2686
Random 3156

Based on this, it doesn't seem like there's a big benefit to adding a caching strategy because we're talking a matter of < 1s difference.

Also, I suspect that the Topic-based banner took less time because the same stories are loaded each time and so some of the values get cached rather than being pulled from the database. With enough page loads, the random banner's performance should improve as the cache gets warmed up.

wendynorris commented 11 years ago

Nice work! ** wendy norris http://about.me/wendynorris ceo + founder :: tekhne media, inc a digital information and media collective 720 281 9378 :: mobile

* http://about.me/wendynorris *

On Sun, Feb 17, 2013 at 7:51 PM, Geoffrey Hing notifications@github.comwrote:

I did some simple testing of page load times using ConfessJshttps://github.com/jamesgpearce/confess

I loaded the homepage 25 times for each method of selecting stories for the banner. These are the results: Banner Type Average Load Time (ms) No Banner 2214 Topic (Arts and Culture) 2686 Random 3156

Based on this, it doesn't seem like there's a big benefit to adding a caching strategy because we're talking a matter of < 1s difference.

Also, I suspect that the Topic-based banner took less time because the same stories are loaded each time and so some of the values get cached rather than being pulled from the database. With enough page loads, the random banner's performance should improve as the cache gets warmed up.

— Reply to this email directly or view it on GitHubhttps://github.com/PitonFoundation/atlas/issues/198#issuecomment-13704476.

ghing commented 11 years ago

I believe this is fully implemented as of 13851b5. I've staged this. Closing.

jwirfs-brock commented 11 years ago

@ghing This can be a separate issue that we open in Iteration 12, but is there a way to make sure stories with the default image (i.e., no featured image) don't go into the banner? It looks find with just one or two, but if more than that get in there it looks a bit funny.

ghing commented 11 years ago

@jwirfs-brock I think it would be better to just go through and set featured images for the stories that don't have an image. This shouldn't happen moving forward with the updated featured image selection flow that we implemented in the previous iteration. The issues of stories without featured assets is sort of documented as #300.

jwirfs-brock commented 11 years ago

@ghing Great, that works. As people start to use the new featured image selection we'll get an idea for whether that insures most stories get a featured image. If we're still ending up without them, we can revisit. Thanks.

On Wed, Feb 20, 2013 at 3:28 PM, Geoffrey Hing notifications@github.comwrote:

@jwirfs-brock https://github.com/jwirfs-brock I think it would be better to just go through and set featured images for the stories that don't have an image. This shouldn't happen moving forward with the updated featured image selection flow that we implemented in the previous iteration. The issues of stories without featured assets is sort of documented as #300 https://github.com/PitonFoundation/atlas/issues/300.

— Reply to this email directly or view it on GitHubhttps://github.com/PitonFoundation/atlas/issues/198#issuecomment-13860842.