Fun colorful background animations triggered by the social nav in this One Pager for developer Matteo Belfiore.
by Rob Hope @robhope via One Page Love
"Mr Branding" is a blog based on RSS for everything related to website branding and website design, it collects its posts from many sites in order to facilitate the updating to the latest technology.
To suggest any source, please contact me: Taha.baba@consultant.com
Fun colorful background animations triggered by the social nav in this One Pager for developer Matteo Belfiore.
The following is a short extract from our book, Researching UX: Analytics, written by Luke Hay. It's the ultimate guide to using analytics for improved user experience. SitePoint Premium members get access with their membership, or you can buy a copy in stores worldwide.
To understand why your users behave the way they do, you first need to get to know them. You may make assumptions about who those users are, but you should be constantly challenging those assumptions, or at least be backing them up with facts.
There’s a lot of data available in your analytics package that will help build up your knowledge of who’s visiting your website. The more you know about your users, the more informed your design decisions can be.
This data can form a useful starting point for many different types of research. One area where this data is particularly helpful is in recruiting people for usability tests. In usability testing, the better the participant matches the target persona, the better the test.
Usability testing should show how “real” users interact with your website, and where they may be experiencing issues. Knowing who your users are will improve the results of your usability testing, and will give you a better chance of uncovering the issues your “real” users are encountering.
The following section looks at the data in your analytics tool that will help build up your understanding of who your users are.
Analyzing how users are finding your website can help you understand more about them, and about the context of their visit.
Different analytics tools will classify “traffic sources” or “channels” in different ways. The following are some typical sources for your traffic:
This analysis can give you a better idea about your users’ intentions. If you’re running a paid search campaign, for example, you’ll be able to see the keywords that were used to find your website (as long as you’ve linked up the Google Analytics and Adwords accounts, and enabled auto-tagging). If users are finding you based on “brand” search terms, you know they’re aware of your company and are searching for you specifically.
Analyzing the behavioral metrics for users, broken down by channel, can help content and marketing teams make decisions about the amount of effort, resources, and budget to dedicate to specific channels. From a UX perspective, it can be useful for identifying problem areas (see Chapter 4), but it also helps to give insight into the mindset of your users. Knowing where your users are coming from can help you to identify whether they’re already familiar with your website, and can start to give you clues about the likely purpose of their visit.
To begin with, it’s a good idea to start by finding out where—geographically speaking—your users come from. This is a very broad level of analysis that will help you focus your research. Looking at the location of your users will show you the role international visitors play in the success of your website. Geodata will also give you insight into the behavior of users on a national and regional level.
Most analytics tools will give you location data for your users. In Google Analytics, this can be found in Audience > Geo > Location. This report will tell you where your users are coming from, and will also allow you to compare behavior metrics (and different dimensions) for users from different countries, regions or cities.
Looking at the percentage of visitors from each country will help you understand the importance of international visitors to your website.
But you need to be careful with your analysis here. Just because no one visits your site from Canada, for example, doesn’t necessarily mean that audience is not important to you. You could be accidentally blocking them! Your marketing efforts may not be reaching where they should, or there may be a whole host of other reasons for the lack of visits. Once again, remember that your website analytics tell you what, but not why.
You may be assuming your website only attracts visitors from your own country, but this report may show that you should also consider the needs of international visitors. This could lead to practical considerations—such as the load speed of your website in other countries, international delivery rates for an ecommerce site, and possible cultural differences between other countries and your own.
Cultural differences based on the country of your visitors can be considerations for both your website’s design and functionality. These differences can be hard to cater for, as cultural differences may be subtle, and often won’t lead to clear ideas for design changes. Still, detailed research on the cultural needs of you users is definitely recommended.
On a more practical level, the way people use ecommerce websites varies dramatically depending on their country. According to data from Worldpay, only 12% of users in Germany make online purchases using cards.
This compares with 63% of UK users and 72% of users in the USA. If you notice that your ecommerce website is getting a lot of visits from Germany, you’ll want to look at offering alternative payment methods. The most popular type of online payment in Germany in real-time bank transfer.
Looking beyond the number of visits, you’ll be able to see behavioral metrics, such as time on site, bounce rate and conversion rate. Focusing on user behavior will enable you to pinpoint particular countries where there may be issues with your website, and thus opportunities to make improvements. If, for example, your ecommerce website is getting a lot of visits from a certain country, or countries, but the conversion rate is low, you may want to reassure those users that you deliver internationally.
There could be many reasons why your conversion rate is low in a particular country. You may not ship to that country, your site may be in the wrong language, the products may be cheaper in that country, or you may not offer the right payment methods (as in the example of Germany). This is where it’s important not to jump to conclusions. Remember, the data only tells you what is happening. It’s important that you set aside research time to find out why.
If you can see an opportunity to increase your conversion rate internationally, you might also want to consider personalizing your website in some way for those countries. This could be as simple as showing the flag of that country and being up front about the exact costs and delivery times for that location. This simple form of personalization will likely resonate with your international users, and will help you unlock potential additional revenue from international sales.
If your analytics shows you’re getting a lot of visits from other countries, you’re likely to be missing out if you don’t factor in cultural differences!
Geo reports can locate users down to state and city level. This means you may also want to assess your visitors by state, region and city to get a clearer picture of who your visitors are and how they behave. The importance of this level of detail will depend on the purpose of your website. For political websites, for example, localized data can be very important to see how a candidate is performing in a key state or region.
Knowing what language your users speak can give you additional insight into the content you should serve up. Language and location are sometimes confused when looking at analytics, but the two dimensions have no direct connection. A user can be located in Paris but speak Spanish. Location is ascertained by the IP address of your user, while their language can be derived from the language settings of their browser.
Continue reading %Getting to Know Your Users With Analytics%
Real unique One Pager featuring an interactive Ouija board that "summons the spirit of Beyonce". Thanks so much for the detailed build notes, really helpful for the community inspecting this type of unique site.
Lovely clear typography in this One Pager explaining design methodology Calling For Wisdom. Really feeling this Anton and Lora font pairing.
Kotlin is a modern programming language that compiles to Java bytecode. It's free and open source, and makes coding for Android even more fun.
In the previous article, you learned more about object-oriented programming by digging into abstract classes, interfaces, inheritance, and type aliases in Kotlin.
In this post, you'll continue to learn about programming in Kotlin by learning about exceptions and how to handle them.
Exceptions are used to indicate a problem in our code during a program's execution. Exception handling is the capability to address (or handle) the exception that might occur. If we don't handle any exception that occurs, our program will stop execution abruptly—crashing our app immediately.
Exception handling allows our program to continue execution even if there was an exception (though it is highly recommended to log your exceptions and report them using a crash reporting tool like Crashlytics).
In Java, we have two kinds of exceptions: checked and unchecked. I'll briefly explain both of them, but we'll start with unchecked exceptions.
These are exceptions that are thrown because of flaws in your code. They are a direct or indirect subclass of the RuntimeException
superclass.
Examples of unchecked exceptions include:
ArithmeticException
: thrown when you divide by zero.ArrayIndexOutOfBoundExceptions
: thrown when an array has been accessed with an illegal index. SecurityException
: thrown by the security manager to indicate a security violation.NullPointerException
: thrown when invoking a method or property on a null object.A method that might throw an unchecked exception doesn't contain any information about the exception thrown on its method declaration.
public Integer divideByZero(Integer numerator, Integer denominator) { return numerator / denominator; } divideByZero(7, 0) // throws ArithmeticException
These types of exception can be prevented by coding right. In the code above, we should have checked if the denominator was zero before performing the operation. For these exceptions, the developer doesn't need to catch the exception using the try...catch
block. In other words, we aren't forced by the compiler to wrap the code that might trigger the exception in a try...catch
block. Instead, we should just make sure the exceptions never occur in the first place.
Also, remember, Kotlin is a null safe language. In other words, it can help us avoid getting NullPointerExceptions
in our code. You can read the Nullability, Loops, and Conditions post to get a refresher on null safety in Kotlin.
A method that might throw a checked exception needs to declare so in its method signature using the throws
keyword. If you call a method that throws a checked exception, you either need to throw it again from your function or to catch it and handle it using a try...catch
block.
Checked exceptions are exceptions that are checked at compile time. These kinds of exceptions inherit from the Exception
class. An example of this kind of exception is IOException
. This can occur when you try to access a file that can't be opened because it doesn't exist. (FileNotFoundException
is a subclass of IOException
.)
// perform in a background thread public void editFile(File file, String text) { try { file.getParentFile().mkdirs(); FileOutputStream fileOutputStream = new FileOutputStream(file); Writer writer = new BufferedWriter(new OutputStreamWriter(fileOutputStream)); try { writer.write(text); writer.flush(); fileOutputStream.getFD().sync(); } finally { writer.close(); } } catch (IOException e) { // Log the exception e.printStackTrace(); } }
In the preceding code, we used a try...catch
block to handle the IOException
inside the editFile()
method. We can now call the editFile()
method as normal, and the compiler won't complain.
editFile(new File(""), "my text");
Looking at the code below, we've refactored the method to instead use the throws
keyword in the method signature. This indicates to callers that they need to handle the exception IOException
that might be thrown when calling the method editFile()
.
// this should be in a background thread public void editFile(File file, String text) throws IOException { file.getParentFile().mkdirs(); FileOutputStream fileOutputStream = new FileOutputStream(file); Writer writer = new BufferedWriter(new OutputStreamWriter(fileOutputStream)); try { writer.write(text); writer.flush(); fileOutputStream.getFD().sync(); } finally { writer.close(); } }
To call the method above, we need to surround it in a try...catch
block to handle the exception.
try { editFile(new File(""), "my text"); } catch (IOException e) { e.printStackTrace(); }
This has been a brief look at exceptions in Java. Let's now see how Kotlin handles exceptions.
The main difference between Kotlin and Java exception mechanisms is that all exceptions are unchecked in Kotlin. In other words, they are not explicitly declared in the function signatures, as they are in Java.
fun editFile(file: File, text: String) { file.parentFile.mkdirs() val fileOutputStream = FileOutputStream(file) val writer = BufferedWriter(OutputStreamWriter(fileOutputStream)) try { writer.write(text) writer.flush() fileOutputStream.fd.sync() } finally { writer.close() } }
Here, we have converted the editFile()
method to a Kotlin function. You can see that the function doesn't have the throws IOException
statement in its function signature. throws
isn't even a keyword in Kotlin.
Also, we can call this function without surrounding it with the try...catch
block—and the compiler won't complain. In other words, there's no such thing as checked exceptions in Kotlin. All exceptions are unchecked. (Note that if there is an exception thrown, program execution will stop as normal.)
If we think this exception might arise, we should still handle it by surrounding the method with a try...catch
block—but this is not enforced by the Kotlin compiler.
try { editFile(File(""), "text 123") } catch (e: IOException) { e.printStackTrace() }
If the exception thrown inside the editFile()
function is an instance of the IOException
class, our catch
block will be executed, and we simply print the stack trace for debugging purposes.
try...catch
BlockThe try
construct with catch
and finally
clauses in Kotlin is similar to that of Java.
fun foo() { try { throw Exception("Exception message") } catch (e: Exception) { println("Exception handled") } finally { println("inside finally block") } }
Here, we are throwing an Exception
object inside the try
block. Notice we didn't include the new
keyword as we do in Java to create a new instance. Also notice that we didn't specify the exception that will be thrown in the function signature as we would have to in Java.
We handle all subclasses and classes of type Exception
in the catch block. The optional finally
block is always executed—this is where we typically close any resources or connections that were previously opened so as to prevent resource leaks. For example, if you open a file or create a database or network connection in a try
block, you should close or free it in a finally
block.
Note that in Kotlin the throw
construct is an expression and can combine with other expressions.
val letter = 'c' val result = if (letter in 'a'..'z') letter else throw IllegalArgumentException("A letter must be between a to z")
Also, the try
construct can be used as an expression.
fun foo(number: Int) { val result = try { if (number != 1) { throw IllegalArgumentException() } true } catch (e: IllegalArgumentException) { false } println(result) } foo(2) // false
Here, we assigned the value returned from the try...catch
block to the result
variable. If the number is not 1
, it throws an IllegalArgumentException
and the catch
block is executed. The false
expression in the catch
block value will be assigned to the result
variable. If the number is 1
instead, then the true
expression value will be assigned to the result
variable.
Exceptions in Kotlin behave as normal in Java—but I want to make you aware of a useful annotation called @Throws
in Kotlin that might come in handy. Because all exceptions in Kotlin are unchecked, developers who consume your Kotlin code from Java might not be aware that your functions throw exceptions. However, you can still add the possible exceptions that might be thrown to a method signature with the @Throw
annotation. This will alert Java callers that they need to handle the exception.
Let's see a practical example of this annotation.
/* Functions.kt file */ fun addNumberToTwo(a: Any): Int { if (a !is Int) { throw IllegalArgumentException("Number must be an integer") } return 2 + a }
Here, we defined a Kotlin function that can throw an exception IllegalArgumentException
only if the type passed to the function is not of type Int
.
We call this top-level function addNumberToTwo()
directly from Java in the following way:
public void myJavaMethod() { Integer result = FunctionsKt.addNumberToTwo(5); System.out.println(result); // 7 }
This works fine; the compiler isn't complaining. However, if we want to communicate with Java callers that the addNumberToTwo()
top-level function throws an exception, we simply add the @Throws
annotation to the function signature.
@Throws(IllegalArgumentException::class) fun addNumberToTwo(a: Any): Int { if(a !is Int) { throw IllegalArgumentException("Number must be an integer") } return 2 + a }
This @Throws
annotation can accept a comma-separated list of arguments of exception classes. In the code above, we just included one exception class—IllegalArgumentException
.
Now we have to update our Java code to handle the exception.
public void myJavaMethod() throws IllegalArgumentException { Integer result = FunctionsKt.addNumberToTwo(5); System.out.println(result); }
If we decompile the Kotlin addNumberToTwo()
function, using the Show Kotlin Bytecode feature (if you're in IntelliJ IDEA or Android Studio, use Tools > Kotlin > Show Kotlin Bytecode), we'll see the following Java code:
// ... public static final int addNumberToTwo(@NotNull Object a) throws IllegalArgumentException { Intrinsics.checkParameterIsNotNull(a, "a"); if (!(a instanceof Integer)) { throw (Throwable)(new IllegalArgumentException("Number must be an integer")); } else { return 2 + ((Number)a).intValue(); } } // ...
In the generated Java code above (some elements of the generated code were removed for brevity's sake), you can see that the compiler added the throws
keyword to the method signature—because we included the @Throws
annotation.
In this tutorial, you learned more about programming in Kotlin by looking into exceptions. We saw that Kotlin doesn't have checked exceptions but that instead, all exceptions are unchecked. We also looked at how to handle exceptions using the try...catch
block and saw the usefulness of the @Throws
annotation in Kotlin for Java callers.
To learn more about the Kotlin language, I recommend visiting the Kotlin documentation. Or check out some of our other Android app development posts here on Envato Tuts!