Just testing out some embedded wave stuff. I'm planning on working on a habari plugin for this. If all you see is the Wave login, then you won't be able to do anything with this. Those that do have a wave login should be able to use the wave.
If you don't see the wave login... Well, I've been having mixed results with that but think I've got the cause nailed down now.
Oct 09, 2009
| Tags: google, plugin and wave | 7 Comments
It's finished! I've uploaded the plugin to the -extras repo, so you can grab it there. The current version requires Habari 0.7 to run. I've gone ahead and made a 0.6 branch. I don't have 0.6 installed anywhere right now to test, so if you get the chance to, let me know if it works or not. Once I find out I'll make a tag for it.
The plugin allows you to create your own dashboard modules for any reports that you want to see. Each module is made up from a XML file which tells the plugin what info we need from Google Analytics, and a PHP template that is used to output the modules display.
The templates have access to all of the data from the report. This way if you need to override anything that the plugin functions would handle you can. A perfect example is actually in one of the default modules, Content Overview. That template outputs the module pane without using any internal functions:
<ul class="items">
<?php foreach ( $data[1] as $k => $v ) { ?>
<li class="item clear">
<span class="message pct75 minor"><?php echo $k; ?></span>
<span class="date pct15 minor"><?php echo $v; ?> views</span>
<span class="comments pct10"><?php echo number_format( (($v / $data_total) * 100), 2); ?>%</span>
</li>
<?php } ?>
</ul>As I mentioned, you can also override any builtin functions that you need to. Googles GeoMap Visualization doesn't seem to properly detect the width of the DIV that it's contained in, so it tends to be wider than what your div actually is. To work around this, in the template, we actually add in a little detection and do the chart options there instead of in the map_overlay.xml.
<div id="div_<?php echo $slug; ?>"></div>
<script type="text/javascript">
// Get the actual width of the div
var divWidth = document.getElementById("div_<?php echo $slug; ?>").offsetWidth;
// Load up our GeoMap options instead of using builtin $js_opts
var opts = {
height: 200,
width: divWidth,
showLegend: false
};
<?php echo $js_data; ?>
<?php echo $js_draw; ?>
</script>So to create your own dashboard modules, just create your report_name.xml and report_name.php in the custom directory. All of your custom modules should go here. I've split this up so that you can upgrade the plugin without losing any custom modules you have already done.
Just to show you how flexible this is, I'll cover how to create a Visitors vs Pageviews module for your dashboard. (Don't worry about copying all of this out. It's available as example_report_1 in the custom directory.) First, we'll create the XML that tells the plugin what dimensions and metrics we want to pull from Google Analytics.
<?xml version="1.0" encoding="utf-8" ?>
<report>
<name>Visits vs Pageviews</name>
<type>linechart</type>
<opts>height: 200, backgroundColor: 'FAFAFA', legendBackgroundColor: 'FAFAFA', legend: 'bottom'</opts>
<sort>none</sort>
<dataReference order="1">
<dimensions>ga:month,ga:day</dimensions>
<metrics>ga:visits</metrics>
<sort>ga:month</sort>
</dataReference>
<dataReference order="2">
<dimensions>ga:month,ga:day</dimensions>
<metrics>ga:pageviews</metrics>
<sort>ga:month</sort>
</dataReference>
<dataTypes>
<row type="string">Date</row>
<row type="number">Visitors</row>
<row type="number">Pageviews</row>
</dataTypes>
</report>
And here's the PHP template that it uses:
<div id="div_<?php echo $slug; ?>"></div>
<script type="text/javascript">
var opts = { <?php echo $js_opts; ?> };
<?php echo $js_data; ?>
<?php echo $js_draw; ?>
</script>Pretty simple, huh? This will output the following on your dashboard module:

Any questions/problems, you can leave a comment here or catch me in #habari.
Jul 26, 2009
| Tags: google, habari and plugin | Leave A Comment
So I've started on a Google Analytics plugin for Habari. It pulls the information from your analytics account and displays it on the dashboard. Here's what it currently looks like:

Yes, I know. It still needs some tweaking. I'm hoping to get this to a point that I can release it up to extras soon. Currently there are four dashboard modules:
- Traffic Sources Overview
- Content Overview
- Visitors Overview
- Map Overlay
These are the same modules that show up on your Analytics desktop as well. The graphs and map are generated using the Google Visualization API, so they're interactive. Click on a data point and get the information for that particular metric.
If you have any suggestions for some other pre-canned reports, let me know.
Jul 19, 2009
| Tags: google, habari and plugin | 1 Comment
I've gotten a few pings on how I generate the maps for my Brightkite entries in my lifestream with Sweetcron. It's pretty simple and straight forward. Looking out on the Google group for Sweetcron, I see that no one really shared what they had done in the past, so here's my implementation. You'll need to get a Google Maps API Key for this to work on your site. If you don't already have one, you can get one here.
First things first. For some reason (I haven't had a chance to dig into it yet) Sweetcron won't import a BK feed directly (at the time of this entry). To work around this just run your BK feed through Feedburner, and then use that as the feed URL in Sweetcron.
Secondly, we'll need to pull some additional information when Sweetcron pulls in the feed. To accomplish this one, we'll create a new class. You can download the class here or just copy out the code below. To install this, simply drop it into your system/application/plugins directory. Make sure to edit the file and update your GOOGLE_MAPS_API_KEY for image generation. (You'll also want to rename the extension from .phps to .php if you download it.)
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
* @todo: Change these to match your setup
*/
define('GOOGLE_MAPS_API_KEY', '!!CHANGE THIS TO YOUR GOOGLE MAPS API KEY!!');
define('IMG_SIZE_CHECKIN', '230x200');
define('IMG_SIZE_MESSAGE', '230x100');
/**
* Namespaces that we'll be working with
*/
define('NS_GEORSS', 'http://www.georss.org/georss');
define('NS_BKITE', 'http://brightkite.com/placeFeed');
define('NS_MEDIA', 'http://search.yahoo.com/mrss');
/**
* Simple Brightkite class for Sweetcron
*/
class Brightkite_com {
function pre_db($item, $original)
{
// First let's pull out the GeoRSS
$_coords = $original->get_item_tags( NS_GEORSS, 'point');
$_name = $original->get_item_tags( NS_GEORSS, 'featurename' );
// Pull the BrightKite Feed info
$_placelink = $original->get_item_tags( NS_BKITE, 'placeLink');
$_type = $original->get_item_tags( NS_BKITE, 'eventType');
// Convert to something we can use
// @todo: Find another way to do this, SimplePie should include a default way.
list( $lat, $long ) = split( " ", $_coords[0]['data'] );
$name = $_name[0]['data'];
$type = $_type[0]['data'];
// Populate data to be saved along with the item.
$item->item_data['geo']['name'] = $name;
$item->item_data['geo']['lat'] = $lat;
$item->item_data['geo']['long'] = $long;
$item->item_data['bk']['placelink'] = $_placelink[0]['data'];
$item->item_data['bk']['type'] = $type;
// Check to see what type of pose this is.
// $type will be set to one of 'photo', 'message', or 'checkin'
if ( $type == "photo" ) {
$_caption = $original->get_item_tags( NS_BKITE, 'photoCaption');
$_imglink = $original->get_item_tags( NS_BKITE, 'photoLink');
$imglink = $_imglink[0]['data'];
$item->item_data['bk']['caption'] = $_caption[0]['data'];
$item->item_data['bk']['imglink'] = $imglink;
}
elseif ( $type == "message" ) {
// @todo: Figure out why SC doesn't pull this by default.
$item->item_data['description'] = $original->get_description();
}
elseif ( $type == "checkin" ) {
// Don't need any additional info. It's just a checkin.
}
return $item;
}
function pre_display($item)
{
// Generate the URL for our image
$mapimg = 'http://maps.google.com/staticmap?center=';
$mapimg .= $item->item_data['geo']['lat'] . ',' . $item->item_data['geo']['long'];
$mapimg .= '&zoom=12&sensor=false&markers=';
$mapimg .= $item->item_data['geo']['lat'] . ',' . $item->item_data['geo']['long'];
$mapimg .= '&key=' . GOOGLE_MAPS_API_KEY . '&size=';
// Make sure to choose the correct size for the image
if ( $item->item_data['bk']['type'] == "message" ) {
$item->item_data['gmapimg'] = $mapimg . IMG_SIZE_MESSAGE;
} else {
$item->item_data['gmapimg'] = $mapimg . IMG_SIZE_CHECKIN;
}
return $item;
}
}
?>So what does this class give us? It gives us access to all of the GeoRSS information along with some extras that we can use in our _activity_feed.php. The following are now available to you in _activity_feed.php in your theme:
/**
* Returns 'type' of BK entry
* This will be 'photo', 'message', or 'checkin'
*/
$item->item_data['bk']['type'];
/**
* For type 'photo'
*/
// URL to image
$item->item_data['bk']['imglink'];
// Caption for image
$item->item_data['bk']['caption'];
/**
* For type 'message'
*/
// Text of our note that we posted
$item->item_data['description']
/**
* For all types
*/
// Link to Brightkite object
$item->item_data['bk']['placelink'];
// Place Name
$item->item_data['geo']['name'];
// Google map image URL
$item->item_data['gmapimg'];
So if you're still wondering how to use this at this point, pretty simple. You just need to modify your _activity_feed.php file (located in your theme directory) to handle the additional data. Here's the loop in mine that builds my lifestream:
// ...
<?php elseif ($item->get_feed_domain() == 'brightkite.com'): ?>
<?php if ( $item->item_data['bk']['type'] == 'photo' ): ?>
<p class="activity_image_text">
<a href="<?php echo $item->get_permalink(); ?>/<?php echo $item->get_name(); ?>">
<?php echo $item->item_data['bk']['caption']; ?>
</a>
<span class="activity_image_content"></span>
</p>
<span class="type_label photo"></span>
<a class="activity_image" href="<?php echo $item->get_original_permalink(); ?>" style="background: url(<?php echo $item->item_data['bk']['imglink']; ?>) center no-repeat;"></a>
<?php elseif ( $item->item_data['bk']['type'] == 'message' ): ?>
<a href="<?php echo $item->item_data['bk']['placelink']; ?>">
<img class="bkite_note" alt="<?php echo $item->item_data['geo']['name']; ?>" src="<?php echo $item->item_data['gmapimg']; ?>">
</a>
<span class="type_label regular"></span>
<div class="inner_container">
<p class="bkite">"<?php echo $item->item_data['description']; ?>"</p>
</div>
<?php elseif ( $item->item_data['bk']['type'] == 'checkin' ): ?>
<p class="checkin">
<a class="checkin" href="<?php echo $item->item_data['bk']['placelink']; ?>">
<img alt="<?php echo $item->item_data['geo']['name']; ?>" src="<?php echo $item->item_data['gmapimg']; ?>">
</a>
Checked in @ <a href="<?php echo $item->item_data['bk']['placelink']; ?>"><?php echo $item->item_data['geo']['name']; ?></a>
<br>
</p>
<?php endif; ?>
<?php elseif (!$item->feed_id): ?>
// ...
This is obviously not the only way to do it, nor the best, but just the way I have it running here. Have fun!
Apr 27, 2009
| Tags: brightkite, google, lifestream, maps, plugin and sweetcron | 2 Comments