{"id":19651111,"url":"https://github.com/mnutt/funnel_cake","last_synced_at":"2025-04-28T16:31:12.349Z","repository":{"id":1076562,"uuid":"919149","full_name":"mnutt/funnel_cake","owner":"mnutt","description":"Sales funnel tracking and visualization plugin for Rails","archived":true,"fork":false,"pushed_at":"2010-09-20T05:34:58.000Z","size":769,"stargazers_count":11,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-14T20:29:35.174Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://transfs.com/devblog","language":"JavaScript","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mnutt.png","metadata":{"files":{"readme":"README.markdown","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2010-09-17T19:02:43.000Z","updated_at":"2024-06-03T22:39:02.000Z","dependencies_parsed_at":"2022-08-16T12:00:17.644Z","dependency_job_id":null,"html_url":"https://github.com/mnutt/funnel_cake","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnutt%2Ffunnel_cake","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnutt%2Ffunnel_cake/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnutt%2Ffunnel_cake/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mnutt%2Ffunnel_cake/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mnutt","download_url":"https://codeload.github.com/mnutt/funnel_cake/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251345880,"owners_count":21574801,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T15:05:20.912Z","updated_at":"2025-04-28T16:31:10.143Z","avatar_url":"https://github.com/mnutt.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Funnel Cake\n\nFunnelCake is a rails engine plugin that provides sales funnel tracking functionality.\n\nWhile there are plenty of web analytics solutions, and many of them offer goal-tracking and even \"funnels\"... many businesses require a higher-level sales tracking tool.  FunnelCake aims to solve this problem by making it easy to track user \"events\" or conversion milestones.  It is designed to easily plug into an existing web app, attaching to your User model and overlaying a finite state machine onto your User's actions.  Controllers and views are included to make it easy to visualize conversion rates throughout your sales funnel.\n\n## Usage\n\nFunnelCake is composed of a few parts:\n\n* Rails Plugin code that can be easily mixed into your existing User model and application controllers:\n  * A User model directive: `has_funnel`, which provides state_machine and tracking capabilities for your existing user model\n  * An ApplicationController directive: `has_visitor_tracking`, which adds a `before_filter` and some utility methods for tracking \"visitors\" to your site and linking them up to Users when they authenticate\n* A core `FunnelCake::Engine` class that contains the logic for calculating conversion rates and other stats\n* A rails engine that provides models and controllers for viewing and managing the funnel event data\n\n### Structure\n\nFunnelCake is designed to record \"funnel events\". These are transitions from any two states in the funnel state machine, for a given user or visitor.  The default class for these events is FunnelEvent, though it can be overridden in the settings (in theory!).  This model is provided as part of the engine, in the /app subdirectory of FunnelCake.\n\nFunnelEvents can belong to either User's and Visitor's.  The plugin is designed to work with your existing User model, by mixing in the required logic when you issue the \"has_funnel\" directive in your model.  The code is designed to work with any User class name, but it has only been tested extensively with the name \"User\".\n\nVisitors are similar to users, except that they are unauthenticated visitors to your site.  Often, you will want to start tracking progress in your funnel *before* visitors actually sign up for an account.  Visitors let you do this, because they are tracked by sending a cookie with a unique hash to new visitors.  Then, when a visitor authenticates to your site, the visitor is synced up with a User id... so that funnel calculations are seamless across visitors and users.  The default class name for visitors is FunnelVisitor, and this class is included in the /app engine subdirectory.\n\n### Visualization\n\nFunnelCake comes with a variety of visualization widgets for viewing different aspects of the analytics data.  These include:\n\n* A whole-system FSM diagram, showing all funnel state and transition stats\n* \"funnel\"-style widgets for viewing conversion stats between two specific states\n* Historical graphing of conversion stats between two states (in \"rate\" or \"absolute\" terms)\n* Dynamic table of historical conversion data\n* Single-stat widgets for displaying a single-number analytics statistic in a dashboard-friendly large-type format (eg:  \"555 New Customers This Month\")\n* Table of visitors eligible-for/entered-into a given state\n\n\n#### REST-ful Views\n\nMost of FunnelCake is designed with a RESTful architecture.  Thus, it exposes useful views for many of the analytics components, such as:\n\n* `/conversions` - an index view of all primary conversions stats\n* `/conversions/state_one-state_two` - a detailed view of the conversion stats from `state_one` to `state_two`\n* `/states` - an index view of all states\n* `/states/state_one` - a detailed view of `state_one`\n* `/stats/entered_state_count?state=state_one` - a view of the `entered_state_count` statistic for `state_one`\n\nIn addition, most of the `:show` actions for these RESTful views also render to JSON, which provides data for the various FunnelCake dashboard widgets.\n\n#### The Overview Page\n\nBecause FunnelCake uses a FSM model for funnel tracking, a FSM-style node graph seemed an appropriate choice for visualizing the entire funnel.  This is especially useful if you have a complex sales process (which might be a problem of its own!!)  The overview also provides a more simplistic, traditional \"funnel\" view, with conversion rates calculated for all of the states that are marked as `:primary=\u003etrue`.\n\n#### Custom Dashboards\n\nFunnelCake is designed to allow developers to easily create new custom dashboards to serve their own business needs.  In includes a handful of simple partials that can be added to any view, allowing the developer to drop in a few lines of Rails ERB-code to place the FunnelCake dashboard widgets that show the data that they are interested in.\n\nThe graph visualization is done using [GraphViz](http://www.graphviz.org/), and the very handy javascript [Canviz](http://code.google.com/p/canviz) project.  The other canvas funnel visualization is my own concoction, using the excellent [ExCanvas](http://excanvas.sourceforge.net) project.  Graphing is done using the excellent [Flotr Javascript Plotting Library](http://solutoire.com/flotr/).\n\nHere is an example of sales funnel visualization using FunnelCake:\n\n![Example Funnel Visualization](http://github.com/jkrall/funnel_cake/raw/master/doc/example_funnel.png)\n\n## Configuration\n\nConfiguration of FunnelCake is fairly simple.  First of all, you need to be on Rails 2.3.  It is possible that this plugin might work with the rails engine plugin and earlier versions of rails... but I make no guarantees.\n\n### Installation\n\nAs a rails engine plugin... FunnelCake comes mostly pre-packaged.  Simply install it in your plugins directory, and you are 95% of the way there.  One remaining issue though: you will need to copy over the public assets and database migrations.  Running this rake command should get you there:\n\n\trake funnel_cake:setup\n\n### User Model Setup\n\nTo install FunnelCake into your User model, simply add the following line:\n\n\thas_funnel\n\nThere are a few options that you can supply to has_funnel, if you decide to name your models differently... but they are not documented here (yet).\n\nIn addition, you will need to create a file that specifies the funnel event states for your application.  The default location and name for this file is:  lib/funnel_cake/user_states.rb.  However, you can use a different file location by supplying `:state_module=\u003e'SomeOtherModule::MyCustomStates'` to the `has_funnel` method.\n\nFunnelCake::UserStates is a simple mixin-module that acts as a container for your states.  It contains a single method, initialize_states, that does all of the setup.  Here's an example config file, for the funnel depicted above:\n\n\tmodule FunnelCake::UserStates\n\t  def initialize_states\n\n\t    funnel_state :page_visited, :primary=\u003etrue\n\t    funnel_state :ccproc_report\n\n\t    funnel_state :auction_form_visited, :primary=\u003etrue\n\t    funnel_state :signup_step_2, :primary=\u003etrue\n\t    funnel_state :signup_step_3\n\t    funnel_state :signup_step_3_previous_statement\n\t    funnel_state :signup_step_4\n\n\t    funnel_state :auction_started, :primary=\u003etrue\n\t    funnel_state :auction_closed, :primary=\u003etrue\n\t    funnel_state :auction_bid_selected, :primary=\u003etrue\n\t    funnel_state :auction_completed\n\t    funnel_state :auction_booked, :primary=\u003etrue\n\n\t    funnel_event :view_page do\n\t      transitions :unknown,                     :page_visited\n\t      transitions :page_visited,                :page_visited\n\t    end\n\t    funnel_event :create_ccproc_report do\n\t      transitions :page_visited,                :ccproc_report\n\t    end\n\n\t    funnel_event :auction_form_visit do\n\t      transitions :page_visited,                :auction_form_visited\n\t      transitions :ccproc_report,               :auction_form_visited\n\t    end\n\t    funnel_event :signup_step_2 do\n\t      transitions :auction_form_visited,        :signup_step_2\n\t    end\n\t    funnel_event :signup_step_3 do\n\t      transitions :signup_step_2,               :signup_step_3\n\t    end\n\t    funnel_event :signup_step_3_previous_statement do\n\t      transitions :signup_step_3,               :signup_step_3_previous_statement\n\t    end\n\t    funnel_event :signup_step_4 do\n\t      transitions :signup_step_3_previous_statement,          :signup_step_4\n\t      transitions :signup_step_3,               :signup_step_4\n\t    end\n\n\t    funnel_event :start_auction do\n\t      transitions :signup_step_4,               :auction_started\n\t    end\n\n\t    funnel_event :close_auction do\n\t      transitions :auction_started,             :auction_closed\n\t    end\n\t    funnel_event :auction_choosebid_email do\n\t      transitions :auction_closed,              :auction_choosebid_emailed\n\t    end\n\t    funnel_event :upload_statement do\n\t      transitions :auction_closed,              :auction_uploaded_statement\n\t      transitions :auction_choosebid_emailed,   :auction_uploaded_statement\n\t    end\n\t    funnel_event :savings_analysis_ready_email do\n\t      transitions :auction_uploaded_statement,  :savings_analysis_ready\n\t    end\n\t    funnel_event :select_bid do\n\t      transitions :auction_closed,              :auction_bid_selected\n\t      transitions :auction_choosebid_emailed,   :auction_bid_selected\n\t      transitions :auction_uploaded_statement,  :auction_bid_selected\n\t      transitions :savings_analysis_ready,      :auction_bid_selected\n\t    end\n\n\t    funnel_event :auction_finish_email do\n\t      transitions :auction_bid_selected,        :auction_finish_emailed\n\t    end\n\t    funnel_event :complete_auction do\n\t      transitions :auction_bid_selected,        :auction_completed\n\t      transitions :auction_finish_emailed,      :auction_completed\n\t    end\n\t    funnel_event :book_auction do\n\t      transitions :auction_finish_emailed,        :auction_booked\n\t      transitions :auction_bid_selected,        :auction_booked\n\t      transitions :auction_completed,           :auction_booked\n\t    end\n\n\t  end\n\tend\n\nPay attention to the naming conventions used here.  While the plugin does not care about the names you use... it is easy to get confused between \"events\" and \"states\".  When triggering funnel events in your application code, you will always use the `funnel_event` names.\n\nFinally, the `state xxxxx, :primary=\u003etrue` lines are only required so that you can tell FunnelCake which states are important for calculating overall conversion rates.  These states will be highlighted in the visualization, and the conversion rates are automatically displayed.  (FunnelCake can calculate conversions between any two states... but it gets complicated if you have lots of branching, so it is best to keep the `:primary` states to those which are true milestones that all users pass through)\n\n### ApplicationController Setup\n\nTo install FunnelCake's visitor tracking into your ApplicationController, add the following:\n\n\thas_visitor_tracking :cookie_name=\u003e:transfs_ut\n\nThe `:cookie_name` argument is what it sounds like.  This is the name of the cookie that FunnelCake will use to track anonymous visitors on your site.\n\n### Triggering Funnel Events in your Application\n\nTo trigger a funnel event in your app... there are a few utility methods available:\n\n\tlog_funnel_event(event, data)\n\tUser.log_funnel_event(event, data)\n\tlog_funnel_page_visit()\n\tsync_funnel_visitor\n\n`log_funnel_event(event, data)` records a generic funnel event.  You can supply optional data, though the only data key that is currently recognized/stored is :url.\n\n`User.log_funnel_event(event, data)` is an exact copy of the above controller method.  In fact, when you call `log_funnel_event()` on the controller, it simply determines if you have a valid user or valid visitor, and sends `log_funnel_event()` on to the model.  Thus, if you have access to a user in a non-controller context (in a Workling task, for instance)... you can still log funnel events by calling the User method directly.  The same is true for the FunnelVisitor model, however there are no obvious reasons why you would want to call this method directly on a visitor instance.\n\n`log_funnel_page_visit` does what it sounds like.  It records a funnel event for the `:view_page event`.  NOTE: if you want to use this method, you need to have a `:view_page` event in your FSM!  This method just calls `log_funnel_event` under the hood.\n\n`sync_funnel_visitor` is a specific method that links up an unauthorized visitor to an authorized user.  This method should be called immediately after you have authenticated a user, usually in your `SessionsController#create` method.\n\n## Credits\n\nFunnelCake was created, and is maintained by [Joshua Krall](http://github.com/jkrall).  More info at [Transparent Development](http://transfs.com/devblog), the [TransFS.com](http://transfs.com) development blog.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmnutt%2Ffunnel_cake","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmnutt%2Ffunnel_cake","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmnutt%2Ffunnel_cake/lists"}