Skip to content

Latest commit

 

History

History
978 lines (726 loc) · 20.8 KB

File metadata and controls

978 lines (726 loc) · 20.8 KB

ReferralBox Gem - Complete Developer Guide

📖 Table of Contents

  1. Quick Start
  2. Installation
  3. Configuration
  4. Flexible Model Support
  5. Core Features
  6. API Reference
  7. Admin Dashboard
  8. Advanced Usage
  9. Troubleshooting
  10. Examples

🚀 Quick Start

Add to your Gemfile and get started in minutes:

# Gemfile
gem 'referral_box'
bundle install
rails generate referral_box:install
rails db:migrate

Visit /referral_box to see your admin dashboard!


📦 Installation

Step 1: Add to Gemfile

# Gemfile
gem 'referral_box'

Step 2: Install Dependencies

bundle install

Step 3: Run Generator

rails generate referral_box:install

This will:

  • Create config/initializers/referral_box.rb
  • Ask if you want to add columns to your model
  • Set up basic configuration

Step 4: Run Migrations

rails db:migrate

This creates:

  • referral_box_transactions table
  • referral_box_referral_logs table
  • Adds referral_code and tier columns to your model table

Step 5: Update Your Model

Add to your model file (e.g., app/models/user.rb, app/models/customer.rb, etc.):

class User < ApplicationRecord  # or Customer, Account, etc.
  has_many :referral_box_transactions, class_name: 'ReferralBox::Transaction', as: :user
  has_many :referrals, class_name: 'User', foreign_key: 'referrer_id'
  belongs_to :referrer, class_name: 'User', optional: true

  before_create :generate_referral_code

  def points_balance
    ReferralBox.balance(self)
  end

  def current_tier
    ReferralBox.tier(self)
  end

  def referral_link
    "#{Rails.application.routes.url_helpers.root_url}?ref=#{referral_code}"
  end

  private

  def generate_referral_code
    return if referral_code.present?

    loop do
      self.referral_code = SecureRandom.alphanumeric(ReferralBox.configuration.referral_code_length).upcase
      break unless User.exists?(referral_code: referral_code)
    end
  end
end

🔄 Flexible Model Support

ReferralBox works with ANY model! You're not limited to just User. Here are examples:

Example 1: Customer Model

# config/initializers/referral_box.rb
ReferralBox.configure do |config|
  config.reference_class_name = 'Customer'
  # ... other config
end

# app/models/customer.rb
class Customer < ApplicationRecord
  has_many :referral_box_transactions, class_name: 'ReferralBox::Transaction', as: :user
  has_many :referrals, class_name: 'Customer', foreign_key: 'referrer_id'
  belongs_to :referrer, class_name: 'Customer', optional: true

  before_create :generate_referral_code

  def points_balance
    ReferralBox.balance(self)
  end

  def current_tier
    ReferralBox.tier(self)
  end

  def referral_link
    "#{Rails.application.routes.url_helpers.root_url}?ref=#{referral_code}"
  end

  private

  def generate_referral_code
    return if referral_code.present?

    loop do
      self.referral_code = SecureRandom.alphanumeric(ReferralBox.configuration.referral_code_length).upcase
      break unless Customer.exists?(referral_code: referral_code)
    end
  end
end

Example 2: Account Model

# config/initializers/referral_box.rb
ReferralBox.configure do |config|
  config.reference_class_name = 'Account'
  # ... other config
end

# app/models/account.rb
class Account < ApplicationRecord
  has_many :referral_box_transactions, class_name: 'ReferralBox::Transaction', as: :user
  has_many :referrals, class_name: 'Account', foreign_key: 'referrer_id'
  belongs_to :referrer, class_name: 'Account', optional: true

  before_create :generate_referral_code

  def points_balance
    ReferralBox.balance(self)
  end

  def current_tier
    ReferralBox.tier(self)
  end

  def referral_link
    "#{Rails.application.routes.url_helpers.root_url}?ref=#{referral_code}"
  end

  private

  def generate_referral_code
    return if referral_code.present?

    loop do
      self.referral_code = SecureRandom.alphanumeric(ReferralBox.configuration.referral_code_length).upcase
      break unless Account.exists?(referral_code: referral_code)
    end
  end
end

Example 3: Member Model

# config/initializers/referral_box.rb
ReferralBox.configure do |config|
  config.reference_class_name = 'Member'
  # ... other config
end

# app/models/member.rb
class Member < ApplicationRecord
  has_many :referral_box_transactions, class_name: 'ReferralBox::Transaction', as: :user
  has_many :referrals, class_name: 'Member', foreign_key: 'referrer_id'
  belongs_to :referrer, class_name: 'Member', optional: true

  before_create :generate_referral_code

  def points_balance
    ReferralBox.balance(self)
  end

  def current_tier
    ReferralBox.tier(self)
  end

  def referral_link
    "#{Rails.application.routes.url_helpers.root_url}?ref=#{referral_code}"
  end

  private

  def generate_referral_code
    return if referral_code.present?

    loop do
      self.referral_code = SecureRandom.alphanumeric(ReferralBox.configuration.referral_code_length).upcase
      break unless Member.exists?(referral_code: referral_code)
    end
  end
end

Migration Examples

For Customer Model:

rails generate migration AddReferralBoxToCustomers referral_code:string tier:string referrer:references

For Account Model:

rails generate migration AddReferralBoxToAccounts referral_code:string tier:string referrer:references

For Member Model:

rails generate migration AddReferralBoxToMembers referral_code:string tier:string referrer:references

Key Points:

  1. Change reference_class_name in your initializer
  2. Update model associations to use your model name
  3. Update generate_referral_code method to use your model
  4. Run appropriate migrations for your model table

Usage with Different Models:

# With Customer model
customer = Customer.create!(email: "john@example.com")
ReferralBox.earn_points(customer, 100)
balance = ReferralBox.balance(customer)

# With Account model
account = Account.create!(name: "Business Account")
ReferralBox.earn_points(account, 100)
tier = ReferralBox.tier(account)

# With Member model
member = Member.create!(username: "john_doe")
ReferralBox.earn_points(member, 100)
referral_link = member.referral_link

⚙️ Configuration

Basic Configuration

# config/initializers/referral_box.rb

ReferralBox.configure do |config|
  # Define your model (User, Customer, Account, Member, etc.)
  config.reference_class_name = 'User'  # or 'Customer', 'Account', etc.

  # Points earning rule
  config.earning_rule = ->(user, event) do
    # Example: earn 10 points per ₹100 spent
    event.amount / 10
  end

  # Tier thresholds
  config.tier_thresholds = {
    "Silver" => 500,
    "Gold" => 1000,
    "Platinum" => 2500
  }

  # Reward multiplier by tier
  config.reward_modifier = ->(user) do
    case user.tier
    when "Silver" then 1.0
    when "Gold" then 1.2
    when "Platinum" then 1.5
    else 1.0
    end
  end

  # Referral rewards
  config.referral_reward = ->(referrer, referee) do
    ReferralBox.earn_points(referrer, 100)
    ReferralBox.earn_points(referee, 50)
  end

  # Points expiration (days)
  config.points_expiry_days = 90

  # Referral code length
  config.referral_code_length = 8

  # Admin dashboard path
  config.admin_route_path = "/referral_box"
end

Configuration Options

Option Type Default Description
reference_class_name String 'User' Your model class name (User, Customer, Account, etc.)
earning_rule Lambda ->(user, event) { 1 } Custom points earning logic
redeem_rule Lambda ->(user, offer) { 100 } Custom points redemption logic
tier_thresholds Hash {"Silver"=>500, "Gold"=>1000, "Platinum"=>2500} Points needed for each tier
reward_modifier Lambda ->(user) { 1.0 } Points multiplier by tier
referral_reward Lambda nil Logic for referral rewards
points_expiry_days Integer 90 Days until points expire
referral_code_length Integer 8 Length of referral codes
admin_route_path String '/referral_box' Admin dashboard URL path
on_tier_changed Lambda nil Callback when user tier changes

🎁 Core Features

1. Points System

Earn Points

# Basic earning
ReferralBox.earn_points(user, 100)

# With event data
ReferralBox.earn_points(user, 100, event: order)

# Custom earning rule (defined in config)
ReferralBox.earn_points(user, order.amount, event: order)

Redeem Points

# Redeem points
ReferralBox.redeem_points(user, 50)

# With offer data
ReferralBox.redeem_points(user, 50, offer: coupon)

Check Balance

# Get current balance
balance = ReferralBox.balance(user)

# Check if user has enough points
if ReferralBox.balance(user) >= 100
  # Process redemption
end

2. Tier System

Automatic Tier Assignment

# Get current tier
tier = ReferralBox.tier(user)
# Returns: "Silver", "Gold", "Platinum", or nil

# Check if user is in specific tier
if ReferralBox.tier(user) == "Gold"
  # Apply Gold tier benefits
end

Tier Change Callback

# In your initializer
config.on_tier_changed = ->(user, old_tier, new_tier) do
  UserMailer.tier_changed(user, old_tier, new_tier).deliver_later
end

3. Referral System

Track Referral Clicks

# Track when someone clicks a referral link
ReferralBox.track_referral(
  ref_code: params[:ref],
  user_agent: request.user_agent,
  ip_address: request.remote_ip
)

Process Referral Signups

# When new user signs up with referral code
ReferralBox.process_referral_signup(new_user, ref_code)

Get Referral Analytics

# Get referral statistics
total_clicks = ReferralBox::ReferralLog.clicked_count
total_conversions = ReferralBox::ReferralLog.converted_count
conversion_rate = ReferralBox::ReferralLog.conversion_rate

📚 API Reference

Core Methods

ReferralBox.earn_points(user, amount, event: nil)

Earns points for a user.

Parameters:

  • user - User object (or Customer, Account, etc.)
  • amount - Points to earn (integer)
  • event - Optional event object for custom earning rules

Returns: Transaction object or false

Example:

transaction = ReferralBox.earn_points(user, 100, event: order)

ReferralBox.redeem_points(user, points, offer: nil)

Redeems points from a user's balance.

Parameters:

  • user - User object (or Customer, Account, etc.)
  • points - Points to redeem (integer)
  • offer - Optional offer object

Returns: Transaction object or false

Example:

transaction = ReferralBox.redeem_points(user, 50, offer: coupon)

ReferralBox.balance(user)

Gets the current points balance for a user.

Parameters:

  • user - User object (or Customer, Account, etc.)

Returns: Integer (points balance)

Example:

balance = ReferralBox.balance(user)

ReferralBox.tier(user)

Gets the current tier for a user.

Parameters:

  • user - User object (or Customer, Account, etc.)

Returns: String (tier name) or nil

Example:

tier = ReferralBox.tier(user)

ReferralBox.track_referral(ref_code:, user_agent: nil, ip_address: nil, referrer: nil)

Tracks a referral link click.

Parameters:

  • ref_code - Referral code (required)
  • user_agent - Browser user agent
  • ip_address - IP address
  • referrer - Referrer URL

Returns: ReferralLog object or false

Example:

log = ReferralBox.track_referral(
  ref_code: params[:ref],
  user_agent: request.user_agent,
  ip_address: request.remote_ip
)

ReferralBox.process_referral_signup(referee, ref_code)

Processes a referral signup.

Parameters:

  • referee - New user who signed up (or Customer, Account, etc.)
  • ref_code - Referral code used

Returns: Boolean (success/failure)

Example:

success = ReferralBox.process_referral_signup(new_user, ref_code)

Model Methods

Model Methods (for any model: User, Customer, Account, etc.)

user.points_balance          # Get points balance
user.current_tier           # Get current tier
user.referral_link          # Get referral link URL
user.total_referrals        # Count total referrals
user.successful_referrals   # Count successful referrals

🖥️ Admin Dashboard

Access Dashboard

Visit: http://your-app.com/referral_box

Dashboard Features

  1. Overview Dashboard

    • Total users, transactions, referrals
    • Conversion rate
    • Recent transactions
    • Top users by points
  2. Users Management

    • List all users with points and tiers
    • View user details
    • See referral codes
  3. Transactions

    • Complete transaction history
    • Filter by type (earn/redeem)
    • Search and pagination
  4. Referrals

    • Referral click tracking
    • Conversion analytics
    • Device and browser stats
  5. Analytics

    • Referral performance
    • Device breakdown
    • Daily click trends

Customize Dashboard Path

# In your initializer
config.admin_route_path = "/admin/referral_box"

🔧 Advanced Usage

Custom Earning Rules

# Points based on order amount
config.earning_rule = ->(user, event) do
  case event.class.name
  when 'Order'
    event.amount / 10  # 10 points per $1
  when 'Review'
    50  # 50 points for reviews
  else
    1   # Default 1 point
  end
end

Custom Tier Logic

# Dynamic tier calculation
config.tier_thresholds = ->(user) do
  if user.vip?
    { "VIP" => 100, "VIP Gold" => 500, "VIP Platinum" => 1000 }
  else
    { "Bronze" => 100, "Silver" => 500, "Gold" => 1000 }
  end
end

Referral Rewards

# Complex referral rewards
config.referral_reward = ->(referrer, referee) do
  # Give referrer points
  ReferralBox.earn_points(referrer, 100)
  
  # Give referee welcome bonus
  ReferralBox.earn_points(referee, 50)
  
  # Send notifications
  ReferralMailer.welcome_bonus(referee).deliver_later
  ReferralMailer.referral_bonus(referrer).deliver_later
end

Points Expiration

# Custom expiration logic
config.points_expiry_days = ->(user, points) do
  if user.vip?
    365  # VIP users get 1 year
  else
    90   # Regular users get 90 days
  end
end

🛠️ Integration Examples

E-commerce Integration

# In your Order model
class Order < ApplicationRecord
  belongs_to :user  # or customer, account, etc.
  
  after_create :award_points
  
  private
  
  def award_points
    ReferralBox.earn_points(user, order_total, event: self)
  end
end

# In your Coupon model
class Coupon < ApplicationRecord
  def apply_to_order(order)
    points_cost = cost_in_points
    if ReferralBox.balance(order.user) >= points_cost
      ReferralBox.redeem_points(order.user, points_cost, offer: self)
      order.apply_discount(discount_amount)
    end
  end
end

Referral Integration

# In your ApplicationController
class ApplicationController < ActionController::Base
  before_action :track_referral
  
  private
  
  def track_referral
    if params[:ref].present?
      ReferralBox.track_referral(
        ref_code: params[:ref],
        user_agent: request.user_agent,
        ip_address: request.remote_ip
      )
    end
  end
end

# In your UsersController (or CustomersController, etc.)
class UsersController < ApplicationController
  def create
    @user = User.new(user_params)
    
    if @user.save
      # Process referral if present
      if session[:referral_code].present?
        ReferralBox.process_referral_signup(@user, session[:referral_code])
      end
      
      redirect_to @user
    else
      render :new
    end
  end
end

API Integration

# API endpoint for points balance
class Api::ReferralBoxController < ApplicationController
  def balance
    render json: {
      balance: ReferralBox.balance(current_user),
      tier: ReferralBox.tier(current_user),
      referral_code: current_user.referral_code
    }
  end
  
  def earn_points
    amount = params[:amount].to_i
    transaction = ReferralBox.earn_points(current_user, amount)
    
    if transaction
      render json: { success: true, new_balance: ReferralBox.balance(current_user) }
    else
      render json: { success: false, error: "Failed to earn points" }
    end
  end
end

🔍 Troubleshooting

Common Issues

1. "undefined method 'page'" Error

Problem: Kaminari pagination not working

Solution: The gem includes Kaminari automatically. If you still get errors, restart your Rails server:

rails server

2. "uninitialized constant ReferralBox" Error

Problem: Gem not loaded properly

Solution:

bundle install
rails server

3. Migration Errors

Problem: Database migration fails

Solution:

rails db:rollback
rails db:migrate

4. Admin Dashboard Not Loading

Problem: Dashboard routes not working

Solution: Check your routes.rb file. The gem should auto-mount at /referral_box.

5. Referral Codes Not Generating

Problem: Referral codes not created automatically

Solution: Make sure your model has the before_create :generate_referral_code callback.

Debug Mode

Enable debug logging:

# In your initializer
ReferralBox.configure do |config|
  config.debug = true
end

Check Configuration

# In Rails console
puts ReferralBox.configuration.reference_class_name
puts ReferralBox.configuration.tier_thresholds

📝 Examples

Complete E-commerce Example

# config/initializers/referral_box.rb
ReferralBox.configure do |config|
  config.reference_class_name = 'Customer'  # Using Customer model
  
  config.earning_rule = ->(customer, event) do
    case event.class.name
    when 'Order'
      event.amount / 10  # 10 points per $1
    when 'Review'
      50  # 50 points for reviews
    when 'Referral'
      100 # 100 points for referrals
    else
      1
    end
  end
  
  config.tier_thresholds = {
    "Bronze" => 100,
    "Silver" => 500,
    "Gold" => 1000,
    "Platinum" => 2500
  }
  
  config.reward_modifier = ->(customer) do
    case customer.tier
    when "Bronze" then 1.0
    when "Silver" then 1.1
    when "Gold" then 1.2
    when "Platinum" then 1.5
    else 1.0
    end
  end
  
  config.referral_reward = ->(referrer, referee) do
    ReferralBox.earn_points(referrer, 100, event: OpenStruct.new(class: { name: 'Referral' }))
    ReferralBox.earn_points(referee, 50, event: OpenStruct.new(class: { name: 'Referral' }))
  end
  
  config.points_expiry_days = 90
  config.referral_code_length = 8
end

Customer Model Example

class Customer < ApplicationRecord
  has_many :referral_box_transactions, class_name: 'ReferralBox::Transaction', as: :user
  has_many :referrals, class_name: 'Customer', foreign_key: 'referrer_id'
  belongs_to :referrer, class_name: 'Customer', optional: true
  
  before_create :generate_referral_code
  
  def points_balance
    ReferralBox.balance(self)
  end
  
  def current_tier
    ReferralBox.tier(self)
  end
  
  def referral_link
    "#{Rails.application.routes.url_helpers.root_url}?ref=#{referral_code}"
  end
  
  def can_redeem?(points)
    ReferralBox.balance(self) >= points
  end
  
  def tier_benefits
    case current_tier
    when "Gold"
      { discount: 0.1, free_shipping: true }
    when "Platinum"
      { discount: 0.15, free_shipping: true, priority_support: true }
    else
      { discount: 0.05, free_shipping: false }
    end
  end
  
  private
  
  def generate_referral_code
    return if referral_code.present?
    
    loop do
      self.referral_code = SecureRandom.alphanumeric(ReferralBox.configuration.referral_code_length).upcase
      break unless Customer.exists?(referral_code: referral_code)
    end
  end
end

🆘 Support

Getting Help

  1. Check the documentation - This guide covers most use cases
  2. Review the examples - See working implementations
  3. Check the admin dashboard - /referral_box for debugging
  4. Use Rails console - Test methods directly

Useful Console Commands

# Test basic functionality
customer = Customer.first  # or User.first, Account.first, etc.
ReferralBox.earn_points(customer, 100)
puts ReferralBox.balance(customer)
puts ReferralBox.tier(customer)

# Check configuration
puts ReferralBox.configuration.reference_class_name
puts ReferralBox.configuration.tier_thresholds

# Test referral tracking
ReferralBox.track_referral(ref_code: customer.referral_code)

# Check transaction history
ReferralBox::Transaction.where(user: customer).count

Version Information

puts ReferralBox::VERSION

📄 License

MIT License - See LICENSE.txt for details.


Happy coding with ReferralBox! 🎉