{"action":"opened","issue":{"url":"https://api.github.com/repos/hasgeek/hasjob/issues/165","labels_url":"https://api.github.com/repos/hasgeek/hasjob/issues/165/labels{/name}","comments_url":"https://api.github.com/repos/hasgeek/hasjob/issues/165/comments","events_url":"https://api.github.com/repos/hasgeek/hasjob/issues/165/events","html_url":"https://github.com/hasgeek/hasjob/issues/165","id":59842976,"number":165,"title":"Promoted listings","user":{"login":"jace","id":26695,"avatar_url":"https://avatars.githubusercontent.com/u/26695?v=3","gravatar_id":"","url":"https://api.github.com/users/jace","html_url":"https://github.com/jace","followers_url":"https://api.github.com/users/jace/followers","following_url":"https://api.github.com/users/jace/following{/other_user}","gists_url":"https://api.github.com/users/jace/gists{/gist_id}","starred_url":"https://api.github.com/users/jace/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jace/subscriptions","organizations_url":"https://api.github.com/users/jace/orgs","repos_url":"https://api.github.com/users/jace/repos","events_url":"https://api.github.com/users/jace/events{/privacy}","received_events_url":"https://api.github.com/users/jace/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":0,"created_at":"2015-03-04T18:53:19Z","updated_at":"2015-03-04T18:53:19Z","closed_at":null,"body":"Promoted (pinned based on targeting criteria) listings on Hasjob require multiple components to be in place. First, assumptions:\r\n\r\n1. Listings will be targeted by whether the user is logged in, the user's location, and optionally, similarity to another job they are looking at.\r\n\r\n2. Listings can be promoted in the index page or in related listings when looking at a job, or both. Since only about 25% of traffic comes to the home page, related listings are a significant opportunity with breadth of inventory. However, the current positioning below a listing isn't optimal; they should be on the side.\r\n\r\n3. Promotions are counted in session-impressions with a limit of two sessions per user. An impression is when a job stickie is displayed to a user. The user may or may not click on an impression. Since this is subject to the quality of the headline written, HasGeek can't be responsible for its performance.\r\n\r\n4. Each session-impression is charged one or more credits, depending on the bid placed. Repeated impressions within the same session are not charged (user refreshing page, etc). However, repeated impressions are not guaranteed if a competing bid is found.\r\n\r\n5. There are only three pinned listings on any page and the highest bidders that match target criteria are selected.\r\n\r\n6. It's unclear whether we should allow targeting by whether the user is logged in or not. Maybe anon impressions can be *free* to protect from mischief such as repeatedly opening an incognito window and refreshing.\r\n\r\nTo achieve this, we'll need the following models:\r\n\r\n1. `CreditTransaction` an increase or decrease of credits available to the user. The credit balance is always calculated as the sum of credit transactions. Transactions may have a financial value if linked to a payment gateway, but could also be grants from an admin, or could be system generated (free credits for signing up, etc).\r\n\r\n2. `PinnedBid` is a bid for having a job pinned against target criteria. It's linked to a `JobPost`, specifies a bid value (credits per impression, higher = greater chance of winning), has a start and end date, has a `CreditTransaction` via which it is funded, and has a `credit_balance` that's updated via a batch job. When the date expires and if there's any balance left, a second `CreditTransaction` refunds the balance to the user.\r\n\r\n3. The existing `JobImpression` gets a new foreign key to `PinnedBid` that records when an impression was the result of a bid and a new boolean column `not_anon` that contains `JobImpression.event_session.user is not None` as a convenience cache value to make counting faster.\r\n\r\n4. `UserJobView` and `UserAnonView` get a `session_count` column mirroring `CampaignView` and `CampaignAnonView`'s `session_count`. These are used to determine when a `PinnedBid` should no longer be considered for a given user. Since counting is only triggered on an impression, a limit of two session-impressions per user will mean there will be at least one impression in a third session, with the pinned stickie disappearing immediately afterwards (since `session_count` is no longer `<= 2`). This is not good news for the bidder as it increments their session-impressions by one without receiving full visibility for that session. That makes `session_count` harder unless we change the `session_count` update to trigger on session timeout (periodic cronjob) or new session creation (within `EventSession.get_session`)."}}