weyewe. learning by doing.

business model, management system, and software Powered by Obtvse

Using youtube video banner as traffic source

Do you want want to use youtube video banner as traffic source? If yes, you should exploit the following behavior:

Youtube will push any flash overlay that is located within first few pixels from the bottom of the video if the viewer hovers on the video.

See image below for better understanding. The image on the left is the video playback UI when viewer is not hovering on the video. The image on the right is the video playback UI when viewer is hovering on the video.

youtube banner insight

Exploiting youtube raised flash overlay

Inspecting further, we know that after the video has been played, Google ads banner will be shown in YouTube video. Most of the video viewer will close the ads banner by clicking the close button on the top right corner of this banner. Based on this user behavior, if we can place our overlay around the click zone (the close button), we can trick user to do certain action: visiting website, visiting youtube page, or even subscribing to the particular page.

exploit based on youtube banner insight


Pay attention for things that you see and use. A little modification might go a long way.

Thanks to TechInAsia article, where I noticed this trick

The shape of growth

This post is still related to my post talking about Paul Graham’s startup = growth


In his post, Graham mentioned that startup that is increasing its metric (user/revenue/etc) at constant rate is bad and it has failed the very first definition of startup since the metric’s increment at constant rate means NO Growth. This might be confusing for you as it was confusing for me at first.

Will you be happy if you have a company that makes revenue 500USD in day 1? Most people will say yes.

Will you be happy if you have a company that makes revenue 500USD in day 1, and increasing by 10 USD everyday? Most people will say f***ing YeS. So were I, or at least before I read Graham’s article.

With that schema, it means that my revenue will look like this:

Day 1: 500 USD

Day 2: 510 USD

Day 3: 520 USD

Day 4: 530 USD

Day 11: 600 USD

However, this will not be a startup that you see on TechCrunch. It will take 2740 years to make total revenue of 10 million USD. Remember, it is just a revenue, not profit. Assuming that the business only makes 20% profit margin, I will only have 2million USD net profit after 27 lifetimes (assuming that I live for 100 years and there is reincarnation and I retains all the knowledge from the previous next life). If I were an investor with 1 billion USD investable fund, this business will not be a business I am wasting my time on.

If we take analogy in physics, this business is similar to a car that has travelled for 500meter with a steady speed of 10 meter/second. There is no acceleration at all. There is no increment in speed. This is not how Ferrari, Bugatti move. Maybe this is how a bicycle move, at constant speed, at risk of deceleration when the cyclist gets tired. Oh, maybe this is how Ferrari moves in bad traffic jam (bad market).

What if the business moves with some forces causing growth?

Things gets faster. Much faster.

Let’s assume that the business profiles fits the distanced travelled by car moving at initial speed and with some acceleration. Of course, in the actual case, the growth will decreases over time because of market saturation.

X = Xo + Vot + 0.5growth*t2

3% growth for every 10 days

It will takes us 50 years to hit 10million USD in total revenue.

9% growth for every 10 days

It will takes us 29 years to hit 10million USD in total revenue.

The time saved by introducing little growth is significant( saved 2690 years for 3% growth, and saved 2711 years for 9% growth).

A little growth makes a big difference. Check out the chart below to see the shape of growth. Growth curves the metric.

How can we introduce growth to our business?

This is where capital comes in. In order to have growth, there has to be certain force to make it happen. Still related to physics, the formula is

F = m * a , in which F is the amount of Force introduced to the vehicle (our business!) and m is the weight of the vehicle (well, there is no direct correlation. But let’s just call it our business’s efficiency to utilize the capital).

Formula: PMF -> Growth Hacking

Startup Poster

Just read an article from 2012 about startup: Startup == Growth by Paul Graham.

This is a must-read for anyone trying to build a company: whether it is a high-growth or non-high-growth. If I could only choose to memorize one sentence from this article, I would have chosen:

For a company to grow really big, it must (a) make something lots of people want, and (b) reach and serve all those people.

That sentence made me thinking because it was the exact same advice my mentor had said:

Any business is just a combination combination of market-marketing-product, with inequal success ratio, depending on the type of product and market. However, for those web application business you are interested on, I would vote on 40-40-20 composition.

Put in mind that my mentor came from shipping background. Yes, it was the business which manages ship that transport containers containing products to destination, closer to the buyer. Brick and Mortar business.

Brick And Mortar

(a) make something lots of people want

This criterion is market and product. Make something people want means product. Lots of People means big market. Essentially, this criterion speaks about Product-Market-Fit (PMF), a topic that is well researched and scrutinized by Steve Blank’s book: Four Steps to Epiphany. Check this link for the summary.

With all these resources, all we need do is to follow the customer development strategy in order to find the Product-Market-Fit described by Steve Blank. The next interesting information to be uncovered is on the tactics: How to actually execute those customer development strategy on daily basis.

(b) reach and serve all those people

This criterion is about marketing. When we have had a PMF (some people call it post early-stage), all we need to do is to put more gas into it, score as much sales as possible, in sustainable manner. Sustainable as in the cost of acquiring customer doesn’t exceed the lifetime value of that customer.

Again, we are lucky. There are methodology to perform marketing on post early-stage startup called Growth Hacking. There are not much study being performed regarding growth hacking. The most overused example is on Hotmail method of growing by attaching one sentence: “Get Your Free Email at Hotmail”.

action plan

I have made a mistake by building a full blown SaaS product before even doing any customer development (Steve Blank would call this Product Development Model). The only data point I gathered before building the application is because it was a custom web app commissioned by a customer, still being used to-date, and solving his problem. I fail to realize that the market might not have the same needs as this customer.

mistake 1

The next plan that I would do:

  1. Segment the target market for customer development

  2. Talk to the customer to undrestand the pain point so that we can build the Minimum Viable Product (MVP)

  3. Try to get pilot project (free 4 months?)

  4. Close the sales

  5. Wait and see if there is product market fit

  6. Growth Hacking.

Stay tuned! I will update my learning.

Parsing with Nokogiri

I love avaxhome.ru. It is a source of knowledge: most of the ebooks posted in that site is most likely well done and a good reference to buy a book.

However, i dislike the ads. It is Flash based that will cause my MacBook Pro’s fan to scream out loud. Not to be sad, I found a solution: parse the site using Ruby + Nokogiri gem.

The source code

Check my code @github.

There are 4 scrapping file:

  1. scrap_index.rb: used to scrap the first page to the N page (you can set it up through the constant PAGE_COUNT in the file. The result will be printed to the file avax_index.txt.

  2. scrap_category.rb: to scrap based on category (ebooks, film, economics,etc). The result will be printed to the file avax_category.txt.

  3. scrap_user.rb: to scrap all posts ever made by a given user by modifying the variable user in the file. The result will be printed to the file avax_user.txt.

  4. scrap_search.rb: to scrap all posts containing the keyword in the title. Change the content of variable search_value in the file to the new keyword. The result will be printed to the file avax_search.txt.

Example output:


Timesheet Tracker

timesheet illustration


Most of the law firm or consulting bills the customer based on the hours worked. Typically, in a given project/assignment, there are more than 5 people involved. Hence, every month, Human Resource department is busy in collating the time sheet (to extract the total hours worked and the details) from each project members. Furthermore, there can be parallel assignment at a given time. Hence, there will be more steps in collating the total hours worked.

The objective of this assignment is to automate the collating process and produce reports:

  1. How did we waste our resources? At what kind of work category (it can be in drafting letter, answering phone, writing report, or even we wasted too much time in transportation)

  2. Where did we waste our resources? At what project that most of our time goes to?

  3. Who wasted the resources? How each of our employee spend their time at (by project and by category).

What we did:

Of course, for every problem, there are solutions on the market, i.e: Microsoft Project among other things. However, we need each of the employee to do their own data entry. Furthermore, we want to reduce training hours in order to get the timesheet tracking started. Hence, we are going for custom solution using Rails and ExtJS.

With our solution, there are 3 roles: admin(create new users, create customer, create project, create work category), report_viewer (view the result), and data_entry (each user to input their own timesheet log).


To setup the application, admin has to create customer, project, and work categories. Each project belongs to customer. Each project has many timesheet_entry. Each timesheet_entry belongs to one work_categories (it has to be selected for analysis).

Example Report generated:

  1. In a given project, who wasted resources within the specified time period

employee_report_by_project 2. In a given project, what kind of activities are using our resources within the specified time period


The code

You can find it @github

Futsal: post mortem

The futsal booking application described here is done.

Technologies used

  1. Rails 4, using devise for authentication and the_role for authorization

  2. ExtJS 4.1.0 + Ext Ensible Calendar

  3. Deployed @Heroku


  1. Multi users

  2. Multi Role: admin, manager, and data_entry

  3. Price Rule: based on the market information, the field’s rent varies depending on the time of the day. Weekend costs more than normal working days. In fact, they put heavy discount on the morning and afternoon of working days

  4. Multi Facilities : in this application, facility is used to describe the futsal fields being rented hourly.

  5. Booking confirmation + Confirmation code

  6. Payment Confirmation

  7. Customer Database

  8. Reporting: number of hours and total $$ received.

The source code

Available @ github.

Futsal Booking App

Futsal field

A friend just built a sports centre consisting 5 badminton fields and 6 futsal fields. Of course, he won’t manage it on his own. He will hire a staff to take the booking, confirm the downpayment if it were advanced booking, confirm the usage start, finish the usage and take the remaining payment.

What if there is update to the finished usage? It can be done by the role admin.

This friend needs reporting as well, such as:

  1. Utilization ratio of the field

  2. Field usage behavior

  3. Total revenue for a specified period

App Design

I am creating an app for this task: UI using Ext JS ( plus a calendar extension from Extensible ), backend using Rails ( ah,my first try on Rails 4).

Things that we need for backend (Rails):

  1. Authentication, using Devise

  2. Role based access control, using TheRole

For the UI layer:

  1. ExtJS MVC

  2. A Calendar, using Extensible

For the UI/UX design: I am modifying ExtJS calendar example application. Check it out:


In the modified view, we will be using card layout with 4 cards:

  1. Calendar, to see the overall bookings of all facilities.

  2. Bookings, to create booking, create advanced payment, confirm booking, and close booking.

  3. Reports, to see the total revenue, facility utilization, and booking pattern.

  4. Master Data, needs to be set up in the beginning (category and facility). The business has many categories (badminton, futsal, billiard, whatever). And each category has many facilities (5 badminton fields, 6 futsal fields, xx billiard tables). Each facility is identified with unique ID/name.

layout, roughly

Booking Process

rough SOP

1. Query for Availability

The whole process is started by the customer querying about facility availability on certain period of time. The staff will input the query to the application, and the application will respond with availability for such facility at that given time period. If there is exact match, the customer can proceed to make the booking. Or else, the staff will give recommendations on available time close to the requested period.

There is a details to be clarified. How sensitive the query and the result should be? By sensitive, I mean how specific can the timing be? In typical flight booking website, the ticket availability is discrete, such as shown below (btw, it is AirAsia flight booking screen capture).

discrete sensitivity

The screen capture shows 3 available flight schedules (discrete and limited):

  1. 14.05 – 16.40

  2. 17.30 – 20.05

  3. 18.45 – 21.30

On the other hand, the scheduling in fustal booking is continuous. Hence , It is possible for the customer to query for: a futsal field from 18.53 – 19.53 , or from 15.55 – 1700. However, were such flexibility and details to be allowed, it would only create confusion for the staff handling the booking. Furthermore, for futsal game to be started, they have to wait for the majority of the player to arrive. Expecting a group to be punctual is difficult.

I propose that the flexibility will be done off-application. In the booking application, we will only allow bookings duration in multiple of 30-minutes quantum. For example: 7.30-9-30, 15.30-19.30. So on and so forth.

This 30-minutes quantum will imply that booking overlapping is allowed on the first 30 minutes of the booking as illustrated below.

Overlapping booking

2. (optional) Create Advanced Booking + Downpayment

If the customer agrees on the available time period (the starting and ending time), they can proceed on using the facility. However, if they are making advanced booking (booking for future usage), they have to make downpayment . Or else, the booking can still be replaced by another customer.

The downpayment amount is determined off-application, but has to be keyed-in on advanced booking confirmation.

3. Using the facility, extending the usage duration, and paying for the usage

The payment for the facility can be performed before/after the usage. On creating the payment, the staff has to key in the start-time, end-time, total billable amount, and discount amount (if there is any).

App Work Plan

Having figured authentication, authorization using Devise and the_role gem, we can proceed to assemble our application.

Being lazy, I will just modify the ExtJS Kitchen Sink example app instead of re-inventing the wheel.

base kitchen sink

In that kitchen sink example app, we can separate the app into 4 regions: Navigation, WorkSheet, Header, Footer. (see the following image)

marked kitchen sink

  1. Navigation It will display menu by using TreeGrid (leaf). When the leaf is clicked, it will change the Worksheet accordingly. Every menu element has authorization attached. If the currentUser is authorized, the menu will be shown. Or else, it will be kept hidden.

  2. Header It will display common menu/action such as Logout and Settings ( change password or email of the current user).

  3. Worksheet It will display the UI for a particular menu, selected from the navigation.

  4. Footer It will just contain a link to weyewe.com. ^_^

Now, we have the UI plan. How about the ExtJS MVC plan? How can we control those views? And how can we put in the authentication+authorization?

My plan for draft #1:

  1. Authentication Controller: the entry point of the whole application. If there is no current user, it will show the Login Form. Or else, it will show ProtectedContent which is basically the modified Kitchen Sink Application’s navigation and worksheet.

  2. Navigation Controller: Upon authentication, ProtectedContent: Navigation and Worksheet. Then, this controller will build the navigation view with menu items in which the currentUser is authorized to view.

  3. Common Controller: to handle clicking on header or footer. Every user, regardless of their role will have authorization to these actions (logout, change password, change email, change profile) controlled by Common Controller.

  4. XXXWorksheet Controller. Replace XXX with any menu item’s name (the one in navigation view).

ExtJS Devise: send auth_token in all requests

Another learning point of Ext JS: you can force ExtJS to send extra_params in all requests. In our case, for the logged-in user to be able to GET or POST any data to the server, it needs to send the auth_token along.

To do it, just append this piece of code inside your Ext.onReady.

var currentUser = Ext.decode( localStorage.getItem('currentUser'));

if( currentUser !== null){
    var auth_token_value = currentUser['auth_token'];

    Ext.Ajax.extraParams = { auth_token: auth_token_value };

Ext.decode return value

In our app, we are storing the currentUser in localStorage. When we need the currentUser, we can always call:

var currentUser = Ext.decode( localStorage.getItem('currentUser'));

Just a thing to note: if there is no item ‘currentUser’ in the localStorage, Ext.decode will return null.