Rabu, 07 September 2011

Data handling Flex mobile development tips


This is Part 1 of a multipart series of articles that cover tips and tricks for Flex mobile development. If you are used to desktop and web programming, you'll find that developing mobile applications presents a new set of challenges. In addition to rethinking your strategies for data persistence and handling, you'll need to take into account screen size and resolution and make trade-offs to manage performance and battery drain. This series of articles will help ease the transition into mobile development by presenting techniques for overcoming these new development challenges.

Handling data is one aspect of mobile development that requires traditional application developers to adopt a different way of thinking. For instance, for many mobile applications it is important to persist (store) data when the user closes or switches away from the application, when an incoming call is received, or when the application is forced to shut down for some other reason. In addition, mobile application Views are destroyed and recreated often. As a result you'll need to think about how to handle your data between views. So, the two main scenarios in which you need to save data are:

Between application executions (that is, when closing and restarting the application)
Between views within your application
This article covers several ways of handling these scenarios.

Using the destructionPolicy attribute to handle data between views

Before diving into the different ways to handle saving data while navigating between views, it's important to understand the View life cycle. In Flex 4.5, only one View is active at any given time. By default, all other Views will be destroyed and recreated when needed. This behavior is controlled by the destructionPolicy property on the View class, which is set to auto by default. If you set the value of this property to never , the View will be cached and hold its state until it is reactivated via a call to navigator.popView() .

Consider the diagram shown in Figure 1. By default (or when you explicitly set destructionPolicy="auto" ), View A will be destroyed when View B is pushed onto the stack, and View B will be destroyed when View C is pushed onto the stack. View A and View B will be recreated each time the view above it in the stack is popped off. When you set destructionPolicy="never" on View A and View B, those views will be deactivated and cached, but not destroyed, when a new view is pushed. Later, when the view above them is popped, they will simply be activated.
Note that even if you set destructionProperty="never" on a View, it will still be recreated if you invoke pushView() to show it again. The caching only works when the View above is popped off the stack to reveal a previous view. Consider the diagram in Figure 2. When View B is pushed for the second time, it will be recreated and no data from the previous showing will be accessible (unless you use another method to persist and retrieve the data).

I created a simple application that starts in View 1 and invokes pushView() to activate View 2. The normal order of events that occur by default (without setting the destructionPolicy property) can be seen in the following trace statements that I inserted in my application:

View 1 being removed in response to screen change ( removing event)
View 2 added to display list ( added event)
View 2 add event ( add event)
View 2 creation complete ( creationComplete event)
View 1 deactivated ( viewDeactivate event)
View 1 is being removed from display list ( removed event)
View 2 activated ( viewActivate event)
Using the data property to handle data between views

Another (and in my opinion more intuitive) option for saving data between views is to use the data property on the View object. This property will save the state of the data in memory so when you return to your View via a push or pop it can be accessed. You can set any type of object on the data property, including a custom class. In the Person class example shown below, the data property is set to a value object. Note that the data property in the view is instantiated and ready before the View is shown so you don't have to worry about it being available.

You can also return data from a popped view by overriding the createReturnObject() method on the View. If your app is showing View A and you push View B, you can then return data from View B to View A by overriding createReturnObject() in View B; for example:

override public function createReturnObject():Object
{
    return person;
}
In this example, person is an instance of a class I have defined in ActionScript:

package model
{
    [Bindable]
    public class Person
    {
        public var person_id:int;
        public var userid:String;
        public var password:String;
        public var fname:String;
        public var lname:String;
        public var city:String;
    }
}
Once back in View A, you can access the returned object using:

data = navigator.poppedViewReturnedObject.object;
Since the object type is actually ViewReturnObject, you have to specify the object property to get the value.

Persisting data between application executions

You have several options for persisting your data between application executions, so that the data is available when the application is restarted after it has been shut down. Flex 4.5 has a built-in persistence mechanism that is accessed via a property named persistNavigatorState on ViewNavigatorApplication or TabbedViewNavigatorApplication. After you set persistNavigatorState to true to enable this mechanism, you can listen for the navigatorStateLoading and navigatorStateSaving events, and perform any handling needed when those events occur. If you want to develop your own custom persistence method, you can call preventDefault() in the events handler.

When using this technique, your root application tag would look something like the following:

<?xml version=”1.0” encoding="utf-8"?>
<s:ViewNavigatorApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                            xmlns:s="library://ns.adobe.com/flex/spark" firstView="views.SampleDataPersistenceHomeView" firstViewData="{person}"
                            persistNavigatorState="true" navigatorStateSaving="onStateSave(event)"
                            navigatorStateLoading="onStateLoad(event)" >
/Applications/Adobe Flash Builder 4.5/sdks/4.5/frameworks/projects/mobilecomponents/src/spark/managers
When you set persistNavigatorState="true" , your application will automatically save the state of its Views and data to a local shared object with the name FXAppCache. If you look at the PersistenceManager.as source code from the Flex 4.5 SDK (on my Mac this file is found under /Applications/Adobe Flash Builder 4.5/sdks/4.5/frameworks/projects/mobilecomponents/src/spark/managers), you will see how this variable is created:

After running your application in the Flash Builder emulator you can look at what was saved by locating the local shared object on your hard drive. On my Mac, the path to the file is:

/Users/hollyschinsky/Library/Preferences/DataPersistence.debug/Local Store/#SharedObjects/DataPersistence.swf/FXAppCache.sol.

Figure 3. Persisted data in the FXAppCache local shared object.
If you need to persist a custom class, such as the Person class in the example above, you'll have to listen for the preinitialize event in the main application and register the class alias; for example:

protected function viewnavigatorapplication1_preinitializeHandler(event:FlexEvent):void
{
    flash.net.registerClassAlias("person",model.Person);
}
Your data will automatically persist when you simply set the persistNavigatorState property to true , but if you would like to add more properties or access the persistence manager, you can do so by using the ViewNavigatorApplication or TabbedViewNavigatorApplication persistenceManager object; for example:

persistenceManager.setProperty("hollysProp","myProperty"); // set my own custom property
persistenceManager.getProperty("hollysProp"); // retrieve the value for my property
If you're accessing it from a View you could use:

FlexGlobals.topLevelApplication.persistenceManager.getProperty("person"); //Retrieves my custom Person class object that was persisted
To see what's going on behind the scenes, it's helpful to open the debugger and take a look at the persistenceManager variable (see Figure 4).


You can see that two additional properties are also saved by default: versionNumber and navigatorState, which is used to restore the views to their previous state.

The main disadvantage with using the default PersistenceManager is that the data is not encrypted. However, you are free to define a custom persistence mechanism using the IPersistenceManager interface. So you might, for example, want to implement an encrypted local store for getting and setting sensitive data. Another minor disadvantage, in some cases, is that this mechanism is intended for small amounts of data. If you have a great deal of data to be saved you would want to use SQLite instead. For a great article that walks through creating a mobile application that writes to a SQLite database, see  Building a mobile employee directory sample with Flex and Flash Builder  by Christophe Coenraets.


Tips for mastering LinkedIn


LinkedIn might not boast the coolest reputation on the social networking block, but with more than 100 million users, the site is bubbling over with career-related connection opportunities.

Hubspot has compiled the ultimate cheat sheet for mastering the most popular social network for professionals with 20 hidden LinkedIn tricks that will take your profile from Joe Schmoe in a cubicle to Joe Schmooze with a sweet job.

A sampling:

1. Claim your vanity URL. Make your profile look more professional and easier to share by claiming your LinkedIn vanity URL. Instead of a URL with a million confusing numbers at the end, it will look nice and clean like this: http://www.linkedin.com/in/priyo73. Do so by going here and clicking "customize your public profile URL" down on the right-hand side.

2. Make your blog/website links sexier. Instead of using the default "My Website"-type anchor text links in your LinkedIn profile, you can change the anchor text to make those links more appealing to people who view your profile. So if you want to increase clicks on the website links you can display on your profile, change the link's anchor text to something more attention-grabbing than the standard options LinkedIn provides. For example, if you want to include a link to your blog, rather than choosing LinkedIn's standard "Blog" anchor text, customize it to include keywords that indicate what your blog is about, like "Internet Marketing Blog." Each profile can display up to 3 website links like this, and they can be customized by editing your profile, clicking edit on your website links, and selecting "Other" in the drop-down menu to customize the anchor text.

3. Search engine optimize your profile. You can also optimize your profile to get found by people searching LinkedIn for key terms with which you want to be associated. Add these keywords to various sections of your profile such as your headline or summary.

4. Take advantage of "Saved Searches." LinkedIn allows users to create up to 3 saved searches. After conducting a search, clicking the “Save This Search” option allows you to save a search and easily run it again later. You can also choose to receive weekly or monthly reminders via email once new members in the network match your saved search criteria. Just click on the “Saved Searches” tab on the Advanced Search options page and select one of your saved searches to run again.

5. Track company buzz. Company Buzz is a helpful application that allows you to track what people are saying about your company and related topics on Twitter. Just install the application and customize your topics to view tweets, trends, and top keywords.

Hacking Google Analytics: Ideas and Tips


Web analytics is a powerful tool made accessible to all of us through awesome free software such as Google Analytics. These tools are designed to satisfy the general needs of every kind of website out there.

That’s why website analytics tools, in general, are very good at offering a fundamental overview of traffic data of a site, but not so good when it comes to answering specific questions.


To get specific questions answered, sometimes you have to work around limitations of your current software.

As a proof of concept, I’ll present three examples/ideas for gathering more information in conjunction with Google Analytics.

The purpose of this article is to present some starting points for your further exploration.

Example 1: Where Do Users Come From?
Google Analytics (and other web analytics tools) does a great job of telling you the last web page the user clicked on that got him/her to your website. This last web page is often called the referrer or referral path.

Knowing where the user was before visiting your site is helpful because you can use this data to analyze and understand how people are getting to your site.

The problem, though, is that not all visitors become customers/users on their first visit to your website. In most circumstances, the majority of customers visit a website a few times before deciding to buy something or become a regular visitor.

Taking action based only on the last referral path, as reported by tools like Google Analytics, might leave many opportunities on the table and might not give you enough actionable information.

Hacking Google Analytics to give you all the referrers of each visitor proves to be pretty difficult, and the reports you get still won’t answer all of your questions.

Here is how you could do it better:

Each time a visitor gets to your website, Google Analytics will look at his referral and note it down in a specific cookie called __utmz.
A JavaScript hack can help you copy that referral information on another cookie that is managed by your website, and not by Google Analytics.
Each time a visitor gets back to the website, Google Analytics will rewrite its own cookies. The JavaScript hack will update (not rewrite) your website cookie by adding the new referral next to the old one.
When a visitor becomes a customer, upload the content of the new cookie to your database, next to your customer details.
Below is a sample of such a script. Feel free to experiment and fine-tune it.


function createCookie(name, value, days) {
  if(days) {
    var date = new Date();
    date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
    var expires = "; expires=" + date.toGMTString();
  }
  else {
    var expires = "";
  }
  document.cookie = name + "=" + value+expires + ";domain=" + window.location.hostname + "; path=/";
}

function readCookie(name) {
  var nameEQ = name + "=";
  var ca = document.cookie.split(';');
  for(var i = 0; i < ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0) == ' ') c = c.substring(1,c.length);
    if (c.indexOf(nameEQ) == 0) {
      return c.substring(nameEQ.length,c.length);
    }
  }
  return null;
}

function googleCookieReferrer() {
  var feed=readCookie("__utmz");
  // If the utmcsr is not found, cancel
  if(feed.indexOf("utmcsr")==-1) {
    return null;
  }
  if(feed != null) {
    // New version cookie
    if(feed.indexOf("%7C") != -1) {
      feed = feed.split("%7C");
      feed = feed[0].split("%3D");
    }
    else {
      // Old version cookie
      feed = feed.split("|");
      feed = feed[0].split("=");
    }

    if(feed[1] != "") {
      return feed[1];
    }
    else {
      return "";
    }
  }
  // Read the Google cookie, and extract the utmcsr parameter from utmz
  var referrer=googleCookieReferrer();
  // If the Google cookie was successfully read, and utmcsr found
  if(referrer != null && referrer != "") {
    // Read our cookie if it exists
    if(readCookie("__rfrr")) {
      // Cookie data
      var feed = readCookie("__rfrr");
      // Temp cookie string
      var feed_temp = feed;
      // This will hold the last referrer in our cookie
      var check = "";
      // Split the data in our cookie
      feed = feed.split("|");

      // If it's the first element, it's a string
      if(feed[feed.length-1] == null) {
        check = feed;
      } else {
      // If multiple elements, it's an array, so get last array item
        check = feed[feed.length-1];
      }

    // If last element != referrer: write cookie and add new referrer
    if(check != referrer) {
      createCookie("__rfrr",feed_temp+"|"+referrer,365);
    }
    // If no cookie found: create and populate
    else {
      createCookie("__rfrr",referrer,365);
    }
  }
}


Once the script is in place, you’ll be able to answer the following questions:

Who are the referrers that drive the most sales (no matter if it’s the first click, the last click, or somewhere in the middle)?
Who are the best first-click referrers that bring converted visitors to the website?
Which referrers do the best job of getting visitors back to the website and convincing them to buy?
Example 2: How Much Do Customers Spend?
The number one question I get from my clients who use Google Analytics ecommerce tracking is: Why are there more/less money or orders shown by Google Analytics than in reality?


The answer: Google Analytics is not an accounting application, and it will almost never show exact figures of your sales. Charge backs, tracking code issues and ecommerce implementation not covering all payment methods are just a few reasons why the information provided by Google Analytics will not be precise.

Here is how you could do it better:

In the admin area of the website, create a special page for reporting sales (if you don’t already have one). Report from your own database figures; include data such as daily sales, orders or average amount paid per order.
Having in place the above JavaScript hack (example 1), add the referrers reports for your orders.
Add some Google Analytics API queries and display behavior data of converted users compared to website average: time spent on site, number of pages, countries or anything else that’s important to your business (i.e., key performance indicators — otherwise known as KPIs).
You’ve just created a professional dashboard for your business that will give you a clear and reliable view on what’s happening.

Example 3: How Successful Is Website Personalization?
Personalizing the experience of your website visitors can bring positive results. For example, according to a Fast Company article, Yahoo!’s personalization algorithm was a key contributing factor to a 270% increase in clicks on the site’s home page compared to 2009.

Here are just a couple of examples on what you could do to personalize experiences for your visitors:

Display personalized messages and call-to-actions to your visitors, based on their referral path. You can start with specific messages for users that come from advertising campaigns by offering them exactly what they’re looking for based on the ad campaign they clicked on.
Change your home page content based on previous behavior (make it an opt-in or opt-out action for your visitors when they sign up, to respect their privacy). Some more advanced coding might be needed, but it would be worth it.
Invite engaged users to your website to subscribe to your newsletter (my company built an online app for this, called PadiAct) or RSS feed, based on their behavior.
Each website has many keywords that drive visitors from search engines on pages that aren’t immediately relevant for those keywords.

With the next add-on to the previous hack, you can display a nice bottom overlay to your visitors that would contain just the information they are looking for. Now that’s good targeting!


// Add this to extend the code in Example 1
function googleCookieKeyword() {
  var feed = readCookie("__utmz");
  // If the utmcsr is not found, cancel
  if(feed.indexOf("utmctr") == -1) {
    return null;
  }

  if(feed!=null) {
    // New version cookie
    if(feed.indexOf("%7C") != -1) {
      feed = feed.split("%7C");
      feed = feed[3].split("%3D");
    }
    else {
      // Old version cookie
      feed = feed.split("|");
      feed = feed[3].split("=");
    }

    if(feed[1] != "") {
      return feed[1];
    }
    else {
      return "";
    }
  }
  else {
    return "";
  }
}

// Read the Google cookie and extract the utmcsr parameter from utmz
var referrer = googleCookieKeyword();

if (referrer == "YOUR_DESIRED_KEYWORD") {
  // Add your code for displaying the content you desire here
}

Conclusion
Actionable web analytics is not something that should be left to generic tools and data-gathering methods. You’d be happy to know that it’s also not something exclusively affordable only to large companies with big budgets.

As long as we can do some basic coding — and as long as we are devoted to meeting the goals of our website — nothing can stop us from hacking our way to great solutions and innovative workarounds.

I hope this article has inspired you to look into how you can gather richer and more refined data from your own analytics software.





Jumat, 24 September 2010

Black Hat SEO, Beware is

For those of you who just heard the term black hat SEO may be confused what is meant by that .. Black Hat SEO?

black hat SEO is to provide a different page of that requested by the search engines with pages that will be shown this gracious visitors. This last method known as cloaking.

Black Hat SEO trying to increase the ranking of a website in a way contrary to the provisions of the search engines, or commit fraud. One black hat SEO techniques is to hide text by making the text color is similar to the background color, save the text inside the div invisible HTML code, or positioning it outside the screen.

Search engines will impose penalties on websites that use black hat SEO, with lower ranking or removing it from the database. This penalty can be imposed on rogue websites automatically, using a specific algorithm or based on reports from visitors who feel cheated.

Is Black Hat SEO is the strategy?

I think people who use black hat seo is the desperation of people because of your blog or web alexa ranking does not go up or not getting PR from Google, or people who do not understand SEO tips, tricks and want to quickly get high traffic with a shortcut or illicit street earlier .

So how good SEO solution?

Learn from the Master-Master SEO in this blogging world, I do not have to mention one by one who is master of SEO, I myself also am not a SEO Master, I just learn from other masters.