GithubHelp home page GithubHelp logo

swifilaboroka / django-ab-project Goto Github PK

View Code? Open in Web Editor NEW

This project forked from vadim-karpenko/django-ab-project

0.0 0.0 0.0 14 KB

Django project for A/B testing, with no dependencies.

License: MIT License

Python 100.00%

django-ab-project's Introduction

Django-AB-project

This package provides four function in utils.py and some models in models.py.

This would be easy to use this package with Generic views in Django, but this can be work properly in functional-based views, just using other two functions.

(You can read about Generic Views in Django here - https://docs.djangoproject.com/en/1.11/topics/class-based-views/)

What is A/B testing?

A/B testing (also known as split testing) is a method of comparing two versions of a webpage against each other to determine which is better for users. AB testing is essentially an experiment where two variations of a page are shown to users in random order (In this package all users are divided to two group, and not needed to registrated in your app) and statistical analysis is used to determine which variation performs better for a given conversion goal.

How to install?

1. Use pip to download this package - pip install django-AB-project
2. Add 'ab', to INSTALLED_APPS in settings.py:
  INSTALLED_APPS = [
    ...
    ...
    'ab',
  ]
  1. Configure your sessions - set in settings.py at the end of file (or where you want):
  SESSION_EXPIRE_AT_BROWSER_CLOSE = True # Coockie's will be destroyed after browser close
  SESSION_COOKIE_AGE = 60 * 60 * 24 # Coockie's will be destroyed after 24 hours

You can edit this lines if you need.

4. Run python manage.py makemigrations, and python manage.py migrate

5. Run server (python manage.py runserver) and go to the admin page. If you see new line named "Ab_Split_Testing" and can click on them without error page - Congratulation! You successfully installed this package.

How to use?

This package have two main function for each version of views
(Generic views version)

Let's imagine we have some ListView in views.py

  from django.views.generic import ListView
  from split_testing.utils import ab_init, success_goal

  class IntroPage(ListView):
    model = YourModel
    template_name = 'pages/intro.html'

First function, called ab_init we need to use when page is loading, to check if user is load this page.

But also, we need some varables (like path to alternative html file, and name for test)

Let's define!

  class IntroPage(ListView):
    model = YourModel
    template_name = 'pages/intro.html'
    alternative_template_name = 'alt_pages/intro.html'
    page_name = 'intro page'

    def dispatch(self, request, *args, **kwargs):
        # init for a/b, add +1 to "Entered"
        ab_init(self)
        # call the view
        return super(IntroPage, self).dispatch(request, *args, **kwargs)

Let see what we got:

   alternative_template_name = 'alt_pages/intro.html'

Here you need to enter a path to your alternative html file, which you want to test with template_name

Next is:

   page_name = 'intro page'

Enter a name for this page(this test will be named like that)

Next scary thing:

    def dispatch(self, request, *args, **kwargs):
        # init for a/b, add +1 to "Entered"
        ab_init(self)
        # call the view
        return super(IntroPage, self).dispatch(request, *args, **kwargs)

This function will be called when page is loading, so it's perfect place where a/b will be initialized

Let's test our page, go to the urls.py, and write this code:

    from django.conf.urls import url
    from . import views

    urlpatterns = [
         url(r'^$', views.IntroPage.as_view(), name='intro_page'),
    ]

Run your server, and go to 127.0.0.1:8000/

If you don't see any error, and page looks like normal - go to the admin page and check "Ab_Split_Testing"!

Here you see new created object, using your page_name. Click on and you will see some data. Run another browser, or re-enter in your browser and load main page again, and you will see changes.

We successfully initialized our test, but we need collect not only users who entered to our page, but also users, who will make success actions. It would be simple if you need to test forms on your page, but we can test other element's too, just use a little bit of JavaScript.

Testing with forms

ab_init method say if user successfully loaded page, and also remember which page need to show in next time, but to make A/B testing come to life, we need some more extra functionality, like when user do successful action.

Hey, but what is "successful action"? you might want to ask. Let's imagine shop page, and big "BUY" button. You need define, which button will give more sales, red or green. You created two pages, which looks like the same, but with different buttons, and then, when users will find your page, system will remember all users, and which percent of them clicked by this button. After a few days\weeks, when you collect enough of information, you will see in percentage, which button makes more revenue.

A useful thing, right? So here we have two ways to do that, first, when we have form on our page:

from django.shortcuts import redirect
from django.views.generic import FormView
from split_testing.utils import ab_init, success_goal

class SecondPage(FormView):
    # A/B testing variables
    template_name = 'pages/second_page.html'
    alternative_template_name = 'alt_pages/second_page.html'
    page_name = 'second page'
    form_class = someForm
    
    def dispatch(self, request, *args, **kwargs):
        # init for a/b, add +1 to "Entered"
        ab_init(self)
        # call the view
        return super(SecondPage, self).dispatch(request, *args, **kwargs)
        
    def form_valid(self, form):
        # Process your forms
        ... 
        ...
        # A/B set successfully goal before redirect
        success_goal(self)
        
        return redirect('third_page')

success_goal(self) is second function what this package implement.

When this function is triggered, system will remember this action, and to prevent when user click by this button a lot, and to not screw up our experiment, will be saved just one click per user.

Testing using JS (jQuery, actually)

First, you need edit your both html files. Just add to bottom of the body tag this function:

  <script type="text/javascript">
    function Sendgoal(url_page) {
      $.ajax({
        url: url_page,
        data: {'is_clicked': 'True',
                csrfmiddlewaretoken: "{{ csrf_token }}"},
        type:"POST",
        success: function (data) {
          console.log('POST success');
        },
      });
    }
  </script>

Then, you need find your button, or link which pressed by user will be send goal to server

<a href='#' onclick="Sendgoal('{% url 'intro_page' %}')">Click me!</a>

Our work in HTML files is done, now we need to edit our IntroPage class, to handle POST requests:

class IntroPage(ListView):
    model = YourModel
    template_name = 'pages/intro.html'
    alternative_template_name = 'alt_pages/intro.html'
    page_name = 'intro page'

    def dispatch(self, request, *args, **kwargs):
        # init for a/b, add +1 to "Entered"
        ab_init(self)
        # call the view
        return super(IntroPage, self).dispatch(request, *args, **kwargs)
        
    def post(self, request, *args, **kwargs):
        is_clicked = request.POST.get('is_clicked')
        if is_clicked == 'True':
            # A/B set success goal
            success_goal(self)
            return JsonResponse({'OK':'OK'})
        # if POST request is not equal what we send in template
        return JsonResponse({'KO':'KO'})

That's it! Your test is ready, try to test it using another browser.

But if you don't know how method post work, lets read it step-by-step:

Here we are define our method, and get from POST request if user actually click our element

def post(self, request, *args, **kwargs):
    is_clicked = request.POST.get('is_clicked')

If is_clicked equal to 'True' string, we will call success_goal method, and save it to the system.

if is_clicked == 'True':
    # A/B set success goal
    success_goal(self)

and then we just return some data into our html, to clarify, if method register or not our goal.


(Method views version)

Coming soon!

django-ab-project's People

Contributors

vadim-karpenko avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.