I'm trying to create a mini analytics page like the one shown on the image below. It's a marketplace and each user has their analytics page with a graph. I've been able to get the views and referrer but my problem is how to go about doing the conversion part.
In my item show action i have something like this:
def show
#item = Item.find_by_rand_no params[:number]
if current_user && current_user.id != #item.owner_id
#item.views.create(item_id: #item.id, ip_address: request.remote_ip, owner_id: #item.owner_id, referrer: request.env["HTTP_REFERER"])
end
end
How do i track the ones that actually bought something so i can get a conversion rate?
Ps: A user may land on the page then click on another item and buy that instead. I also want to be able to account for that scenario.
Thanks
In your application controller create a before filter e.g. before_filter :save_referrer
def save_referrer
unless session['referrer']
session['referrer'] = request.env["HTTP_REFERER"] || 'none'
end
end
When a user buys an item you can save the referrer in a field either in the order table or create a separate table for referrals which i think is the better option, you can store views for each referrer by counter caching that column. You can also use first_or_create if you don't want to have to group by the referrer column and so on, it's up to you. Anyway you get conversion like this;
Conversion = (Sales/Number of unique views for a referrer) * 100
Related
I have a user_id column. Instead of calling for all members how can I call up members based on current user's and user_id?
This is my controller, I tried changing .all to user_id or current_user.id plus many variations based on examples. Still can't get it. I also have no models (using authrocket). The create action also works and inserts the user_id, I have a def current_user at the bottom.
class Members::MainsController < ApplicationController
# Member Profile List
def index
#members_mains.user_id = current_user.id
#members_mains = Members::Main.all
end
private
# Common Callbacks
def set_members_main
#members_main = Members::Main.find(params[:id])
end
# White List
def members_main_params
params.require(:members_main).permit(:mfirstname, :mlastname, :mtitle, :memail, :mphone, :mnotes, :smfacebook, :smtwitter, :smlinkedin, :user_id)
end
end
If I got it right, your index action should be something like this:
# Member Profile List
def index
#current_member = Members::Main.find(current_user.id)
end
Do you intend to show a list of profiles for all members?
If not, your index action can simply be removed. If so, you wouldn't normally filter on a user_id at all for that action and you can remove that line.
To load a member profile for a specific user_id, try a show action something like this:
def show
#members_main = Members::Main.find_by(user_id: params[:id])
end
That will load a member profile based on the :id from the URL.
If you want to just show the current user's own profile instead, use current_user.id which will give you the AuthRocket user's ID.
def show
#members_main = Members::Main.find_by(user_id: current_user.id)
end
In either case, you may need to remove :show from the set_members_main callback.
Lastly, you probably want to remove :user_id from members_main_params so that users can't modify the AuthRocket user_id. You only want to control that directly (as you already are in the create action).
Hopefully that's clear enough to get you on your way, but I could be off a bit based on what functionality you actually intend for index and show.
I have set up devise and added a way for users to save settings or preferences. For simplicity lets say that the setting is set as a boolean in the users table.
A simple version of what I want is for a user to have a size preference.
If a user is logged in and they visit the home page (products#index) I would like them to only see products that match the setting they have selected. (obviously the product has a size field)
I also have search enabled for the products and would like to keep that functionality intact for the user using their settings
def index
#products = Product.text_search(params[:query]).page(params[:page]).per_page(50)
##products = Product.all
respond_with(#products)
end
What is the best way to go about this?
def index
#products = Product.where(size: current_user.size).text_search(params[:query]).page(params[:page]).per_page(50)
##products = Product.all
respond_with(#products)
end
Should solve your issue
I am new to rails, I have one model named "Topic", I want to get users those are currently viewing topic index page.
How do I get those users, can anybody help me?
Thanks in advance
Here is article which describe how to track active/online users use Redis. You can use this approach to track users who are currently viewing your page.
I would do this like so:
Similar to Jack Hardcastle's suggestion, you could have a column in the users table in your db which stores the path part of a user's url, and another column called "last_seen_at"
:string last_viewed_page
:datetime last_seen_at
Then, in your ApplicationController you could have a before_filter like this:
#in ApplicationController
before_action :set_last_seen_at_and_last_viewed_page
def set_last_seen_at_and_last_viewed_page
if current_user && request.method == :get
current_user.update_attributes(:last_seen_at => Time.now, :last_viewed_page => request.path)
end
end
The reason i test that request.method == :get is that this will only include pages that they actually load in the browser, and see the address in their address bar, and not form submission urls which are usually hidden from the user.
So, now you have the data, it's easy to query. We can never know who is on a page at this exact moment, since we don't know what they are actually doing - they might have gone to the toilet or closed their computer. We can only say that "this page is the last page these people looked at, and they did so within the last 15 minutes" or whatever.
So, if we wanted to use that criteria, of the last 15 minutes, we could say
#current_path = request.path
#users_on_current_path = User.where(["last_seen_at > ? and last_viewed_page = ?", 15.minutes.ago, #current_path])
Any user can 'like' photos on my site. But if he presses the button many times (10 for example), the 10 post requests will be sent to the server.
I tried to solve with the help of sessions.
I thought this code would take likes only each 5 seconds. But it doesnt! There are my action and before_filter:
def like
photo.create_like if session[:voted].nil?
session[:voted] = Time.now.to_a.first(3).reverse.join
redirect_to root_path
end
def check_session
a = Time.now.to_a.first(3).reverse.join
b = a.to_i - session[:voted].to_i
session[:voted] = nil if b >= 5
end
You can't do this with sessions (at least not with the default session store): by default rails stores the session in a cookie.
Cookies are sent by the browser as part of the request, and the response from your server can optionally update them. If you click on your like button several times in quick succession then you'll fire off several requests, each containing cookie data representing the current state of the session. Your response updates the session, but it's too late for the requests that have already been sent - their session data has been already been sent to the server and won't include any changes made by the responses.
As others have said, a bandaid is to use Javascript to restrict multiple submission but the only robust way to deal with this is at the database level ( with a unique index on the likes table).
You forgot reverse in your like method, so the comparison doesn't work. It should be:
session[:voted] = Time.now.to_a.first(3).reverse.join
Also in like you're using session[:voted] and in check_session you're using session[:time].
Although this won't work perfectly either. It would be better to use a Unix timestamp for this and let check_session return a boolean. Something like this:
def like
photo.create_like if check_session
session[:voted] = Time.now.to_i
redirect_to root_path
end
def check_session
session[:voted].blank? || (Time.now.to_i - session[:voted]) > 5
end
disable the button with
<%= submit_tag "Login", 'data-disable-with' => "Please wait.." %>
You could add a conditional in your views to show voted or want to vote? if the user voted already
I have a feature called "Browse" that allows users to browse through random profiles. When a user clicks on "browse" they are immediately taken to a users profile that they are NOT already friends with. What should my controller look like?
Right now I've got:
def browse
#users = User.all.offset(rand(current_user.matches.count))
#users.each do |user|
if !current_user.friends.include?(user)
#user = user
return
end
end
end
However that doesn't seem to be working. Any advice? I am admittedly bad with blocks, it seems!
You could try something like this
def browse
#user = (User.all - current_user.friends).sample
end
A better version would be
def browse
#user = User.where('id not in (?)', current_user.friends.map(&:id))
.offset(rand(current_user.matches.count)).limit(1)
end
Also, if you are too concerned about performance, instead of using the offset technique, better use the randumb gem to fetch the random record. It uses database specific functions for selecting random records, if available.
Add an extra method to your User, something like this:
def random_stranger
self.class.where(%Q{
id not in (
select friend_id
from friends
where user_id = ?
}, self.id).
order('random()').
limit(1).
first
end
Then in your controller:
def browse
#user = current_user.random_stranger
end
If your database doesn't know how to optimize that not in then you could replace it with a LEFT OUTER JOIN combined with WHERE friend_id is null.