Wednesday, August 1, 2012

The power of places and big data for good: Google Places API Developer Challenge 2012

How would you make your community or local government run better? In our first Google Places API Developer Challenge, we’re inviting developers around the world to make something that improves their communities or governments by using the Google Places API and its database of places and tools. The developers of the winning applications will receive a VIP experience at Google I/O 2013.



You might create an app or site that solves health problems, understands crime patterns, or improves commerce. You can use any platform as long as you build with the Google Places API and it benefits your community or government. We’re looking for your best and most innovative ideas.







Built on the comprehensive global database of more than 95 million places that powers Google Maps, the Google Places API enables you to search for information about a variety of nearby places such as establishments, geographic locations and prominent points of interest. You can re-rank place results based on user check-ins, and create new places specific to your app.



To help you develop your ideas and build better apps, we’ve been working with local government officials in Austin, Boston, Chicago, London, Louisville, New York City, Philadelphia, Portland (Ore.), San Francisco, and Seattle along with the White House to surface a wide variety of data sets for your apps. You can find these data sets and more on the Google Places API Challenge site at http://developers.google.com/challenge and hear more about what cities have to say about the challenge here. You can also follow updates and hangouts about the challenge on +Google Maps API.



The submission window opens on August 15th and closes on October 31st, 2012.



We look forward to seeing what can happen when your imagination and the Google Places API come together!



Getting AdMob ads to work with cocos2D Part 2: Handling Autorotation

In the first part of this series, we talked about integrating AdMob ads in a cocos2d application without diminishing performance. However, we conveniently overlooked how you’d go about handling device reorientation. This blog post will outline the two steps necessary for getting autorotation to work using v0.99.5b3 or higher of the cocos2d framework.




Step One: Setting UIKit Autorotation

cocos2d allows you to handle autorotation in two different ways (UIKit and cocos2d). Since we’re working with both UIKit views as well as Open GL views, we want to rely on UIKit autorotation. If not, we’d have to transform our GADBannerView manually. To make sure you’re using UIKit autorotation, set the GAME_AUTOROTATION directive on your platform of choice to kGameAutorotationUIViewController.



Once you’ve done this, check RootViewController.m to make sure shouldAutorotateToInterfaceOrientation: returns YES for all of the orientations that you support. cocos2d produces skeleton code that handles this method differently depending on the autorotation method you’re using, so make sure that you modify the code block where GAME_AUTOROTATION == kGameAutorotationUIViewController.




Step Two: Modifying View Layout

The final step is to modify our resizeViews: method so that it takes the orientation of the device into account when laying out the views. Rewrite resizeViews: as resizeViewForOrientation:, using the orientation parameter to lay out your GADBannerView. The code below, similar to the first blog post, assumes you’re laying out your banner at the top of the screen.




- (void)resizeViewsForOrientation:(UIInterfaceOrientation)toInt {
// If the banner hasn't been created yet, no need for resizing views.
if (!bannerView_) {
return;
}

BOOL adIsShowing = [self.view.subviews containsObject:bannerView_];
if (!adIsShowing) {
return;
}

// Frame of the main RootViewController which we call the root view.
CGRect rootViewFrame = self.view.frame;
// Frame of the main RootViewController view that holds the cocos2d view.
CGRect glViewFrame = [[CCDirector sharedDirector] openGLView].frame;
CGRect bannerViewFrame = bannerView_.frame;
CGRect frame = bannerViewFrame;
// The updated x and y coordinates for the origin of the banner.
CGFloat yLocation = 0.0;
CGFloat xLocation = 0.0;

// Move the root view underneath the ad banner.
glViewFrame.origin.y = bannerViewFrame.size.height;
// Center the banner using the value of the origin.
if (UIInterfaceOrientationIsLandscape(toInt)) {
// The superView has not had its width and height updated yet so
// use those values for the x and y of the new origin respectively.
xLocation = (rootViewFrame.size.height -
bannerViewFrame.size.width) / 2.0;
} else {
xLocation = (rootViewFrame.size.width -
bannerViewFrame.size.width) / 2.0;
}

frame.origin = CGPointMake(xLocation, yLocation);
bannerView_.frame = frame;

if (UIInterfaceOrientationIsLandscape(toInt)) {
// The super view's frame hasn't been updated so use its width
// as the height.
glViewFrame.size.height = rootViewFrame.size.width -
bannerViewFrame.size.height;
glViewFrame.size.width = rootViewFrame.size.height;
} else {
glViewFrame.size.height = rootViewFrame.size.height -
bannerViewFrame.size.height;
}
[[CCDirector sharedDirector] openGLView].frame = glViewFrame;

}


Now that you’re handling rotation, you’re going to have to resize your views in two different places. We’ve already covered this in initGADBanner: in the first post (simply use the interfaceOrientation property of UIViewController to call resizeViewsForOrientation: instead of resizeViews:). Here, we also have to call resizeviewsForOrientation: in willRotateToInterfaceOrientation:duration: as well. You can add this call after the skeleton code that cocos2d provides.



Ads inside your cocos2d application should now stay docked in place whenever device rotations occur. You can check out a full example from this blog post here. As always, feel free to direct any questions you have to our forum or join us for our upcoming hangout.





Custom color picker in Google Calendar


Google Calendar users have had the ability to change the colors of specific events or calendars from a default color palette. Users can now choose a custom color if the default palette does not meet their needs.



Release track:


Rapid



Editions included:


Google Apps, Google Apps for Business, Government and Education



How to access what's new:


Click on "Choose custom color" on the bottom of the existing color picker.



For more information:


http://support.google.com/calendar/bin/answer.py?hl=en&answer=37227



whatsnew.googleapps.com


Get these product update alerts by email


Subscribe to the RSS feed of these updates

Scheduled Release track features update 7/31/12


- Documents: Users will have the ability to create documents offline. You must be running the latest version of Chrome or ChromeOS and install the Google Drive Chrome app to use this feature.



The following features are intended for release to these domains on August 7th:

No new features to announce.



Release track: 

Scheduled*



Editions included: 

Google Apps, Google Apps for Business, Government and Education



For more information:

http://googledocs.blogspot.com/2012/07/offline-updates-and-quick-look-back-at.html

http://support.google.com/docs/bin/answer.py?hl=en&hlrm=en&answer=1628469



*Scheduled Release track: Domains with ‘Scheduled Release’ option enabled in the administrator control panel. Learn more.



whatsnew.googleapps.com


Get these product update alerts by email


Subscribe to the RSS feed of these updates

Tuesday, July 31, 2012

Getting AdMob ads to work with cocos2D

cocos2d for iPhone is a popular framework for building 2D games for iOS. Integrating AdMob ads into cocos2d apps has gotten significantly easier with the latest version of the framework; This blog post will show you three things to keep in mind using v0.99.5b3 or higher of the cocos2d framework. It is assumed that you already have some familiarity with cocos2d.




Initialization

Create and initialize a GADBannerView in the RootViewController class. You can put this code into a new method knowing that it will be called from the AppDelegate after the view hierarchy has been set up. This code adds to the standard banner view example in the docs.




- (void)initGADBanner {

// NOTE:
// Add your publisher ID here and fill in the GADAdSize constant for
// the ad you would like to request.
bannerView_ = [[GADBannerView alloc] initWithAdSize:kGADAdSizeBanner];
bannerView_.adUnitID = @"PUBLISHER_ID_HERE";
bannerView_.delegate = self;
[bannerView_ setRootViewController:self];

[self.view addSubview:bannerView_];
[bannerView_ loadRequest:[self createRequest]];
// Use the status bar orientation since we haven't signed up for
// orientation change notifications for this class.
[self resizeViews];
}



Performance Considerations

Notice the addSubview: in initGADBanner:. Why did we add the GADBannerView directly to the RootViewController’s hierarchy instead of the cocos2d scene’s hierarchy? cocos2d scenes are OpenGL views, whereas our GADBannerView is a UIWebView wrapped in a native UIView. OpenGL views will usually be refreshed often, whereas our GADBannerView will be mostly static. Placing our GADBannerView on top of the OpenGL view therefore can lead to a performance decrease as the device will have more drawing to do.



You can test if this performance decrease is significant for your specific project by logging the frame rate when you place the ad within the OpenGL view and outside of it. The performance cost is usually only significant when you are dealing with very complex hierarchies.




View Layout

Since we’ve decided to place our GADBannerView into the RootViewController’s view hierarchy, we also need to now make sure to resize our cocos2d view to make space for our GADBannerView. The resizeViews: in initGADBanner: is called for this purpose. The implementation for resizeViews: is below. The main OpenGL view which encompasses all of the cocos2d scenes can be grabbed using the +sharedDirector object. The code below assumes you’re going to display the ad at the top of your screen, and have a device that’s in landscape.





- (void)resizeViews: {
// If the banner hasn't been created yet, no need for resizing views.
if (!bannerView_) {
return;
}
// If ad is not showing, no need to resize views.
BOOL adIsShowing = [self.view.subviews containsObject:bannerView_];
if (!adIsShowing) {
return;
}

// Frame of the main RootViewController which we call the root view.
CGRect rootViewFrame = self.view.frame;
// Frame of the main RootViewController view that holds the cocos2d view.
CGRect glViewFrame = [[CCDirector sharedDirector] openGLView].frame;
CGRect bannerViewFrame = bannerView_.frame;
CGRect frame = bannerViewFrame;
// The updated x and y coordinates for the origin of the banner.
CGFloat yLocation = 0.0;
CGFloat xLocation = 0.0;

// Move the root view underneath the ad banner.
glViewFrame.origin.y = bannerViewFrame.size.height;
// The superView has not had its width and height updated yet so use those
// values for the x and y of the new origin respectively. The game is in
// landscape.
xLocation = (rootViewFrame.size.height -
bannerViewFrame.size.width) / 2.0;

frame.origin = CGPointMake(xLocation, yLocation);
bannerView_.frame = frame;


// The super view's frame hasn't been updated so use its width
// as the height. Assume device is in landscape.
glViewFrame.size.height = rootViewFrame.size.width -
bannerViewFrame.size.height;
glViewFrame.size.width = rootViewFrame.size.height;

[[CCDirector sharedDirector] openGLView].frame = glViewFrame;
}



With that, you should now see AdMob ads show up in your cocos2d application. Look out for a follow-up to this blog post where we will discuss how to handle autorotation. As always, feel free to direct any questions you have to our forum or join us for our upcoming hangout.





Introducing the Multi-Channel Funnels Reporting API

Measuring how marketing efforts influence conversions can be difficult, especially when your customers interact with multiple marketing channels over time before converting. Last fall, we launched Multi-Channel Funnels in Google Analytics, a new set of reports that help shed light on the full path users follow to conversion, rather than just the last click. One request we’ve had since the beginning was to make this data available via an API to allow developers to extend and automate use cases with the data. So today we’re releasing the new Google Analytics Multi-Channel Funnels Reporting API.



The API allows you to query for metrics like Assisted Conversions, First Interactions Conversions, and Last Interaction conversions, as well as Top Paths, Path Length and Time Lag, to incorporate conversion path data into your applications. Key use cases we’ve seen so far involve combining this conversion path data with other data sources, such as cost data, creating new visualizations, as well as using this data to automate processes such as bidding.



For example, Cardinal Path used the new Multi-Channel Funnels API, Analytics Canvas ETL (Extract, Transform, Load) and Tableau Software to help their client, C3 Presents, uncover how time and channels affected Lollapalooza ticket sales in an analysis dubbed “MCF DNA.” The outcome was a new visualization, similar to a DNA graph, that helped shed light on how channels appeared throughout the conversion funnel.






MCF DNA Visualization in Tableu Software





In another case, Mazeberry, an analytics company from France, helped their client 123Fleurs decrease customer acquisition costs by 20% by integrating data from the Multi-Channel Funnels API into a new reporting framework. Their application, Mazeberry Express, combines media cost and full conversion path data to provide new Cost Per Acquisition (CPA) and Return on Investment (ROI) metrics that provide a more complete understanding of how online channels are working together to influence conversions.






Mazeberry Express Screenshot - Focus on a Channel





Please note that this functionality only works with the new v3.0 API libraries, so you should upgrade now if you haven’t already (see our migration guide). We look forward to seeing how you make use of this new data source.







Monday, July 30, 2012

Socialize and grow your blog with Google+



Blogger lets you share your thoughts, grow your readership, and engage with your audience. But we want to make Blogger even better by letting you tap into the growing Google+ community. Today, we’re adding a new “Google+” tab in the Blogger dashboard, so you now have a central place to start growing your blog with Google+. This means you can now:

Connect your blog to a Google+ profile or page
If you blog under your own name, you’ve already been able to associate your blog with your personal Google+ profile.  Starting today, you can now connect your blog to a Google+ page for your brand, business or organization.


Notify followers when you publish, and let them recommend your content
Each time you post on your blog, we'll show you a Google+ share box to let you notify followers that you have new blog content.  If they like what you share, followers can +1 or reshare your post to their own friends on Google+. This ripple effect exposes links to your content to a wider audience.




Build enduring connections with your audience
Adding the Google+ gadget to your blog makes it easy for people to add your profile or page to their circles when they like something you’ve published. Forming connections with readers that last after they've left your blog is essential.  

To get started, click the “Google+” tab in the Blogger dashboard and then the “Upgrade” button. If you’ve already upgraded to Google+, we’ll help you associate your blog with your profile or page.




We'll be introducing more settings on this tab in the future, so stay tuned for additional ways to get more out of Blogger with Google+.  If you have questions, you can learn more in our Help Center.