by jeffknupp

jeffknupp /bull

Bull always charges!

139 Stars 29 Forks Last release: Not found 49 Commits 0 Releases

Available items

No Items, yet!

The developer of this repository has not created any items for sale yet. Need a bug fixed? Help with integration? A different license? Create a request here:

always charges...

Build Status Coverage Status

WTF is

On a Friday evening, not too long ago, I was lamenting the shortcomings of the various services I've used to sell my digital book from my personal website. Digital goods sales should be a solved problem by now, but I ran into all sorts of issues when trying to send updates to customers and integrate properly with Google Analytics.

Long story short, I took two hours and wrote a replacement using Python, Flask, SQLAlchemy, and Stripe (as the payment processor).

is to set up on your own domain. Why does the fact that
runs on your own domain matter? Because it makes Google Analytics happy and report conversions properly.

The only things you need to get started using

are a Stripe account (free) and a web server (free?).


  1. pip install bull
    . This installs the
    command, which helps setup your environment
  2. bull setup
    . This creates a directory named
    with the following contents:
    • app.py
      : the main application script.
      can be used to run
      as a WSGI application
    • config.py
      's configuration file. This must be edited to contain your installation-specific configuration details.
    • files
      directory: The directory that contains the files for your digital products
  3. Add product entries to the database (use
    as a model)
  4. (Optional) Create an admin user for viewing
    by running
  5. Add
    to your web server's configuration
  6. Profit! (...literally)

Analytics and Login

supports simple sales analytics at the
endpoint. It requires authorization, which in turn requires you to create (at least one) user using the
script. To see the reports, hit
, log in, and from then on you can go directly to
to see reporting data. You should be good to go after that, and no one else will be able to see the reports.

If for some reason you need to logout, there is also a

endpoint which will log you out (which should use HTTP POST instead of GET, but whatever).

Reporting includes:

  • Email addresses and sales totals of recent purchases
  • Sales data broken down by calendar day
  • Sales charts based on revenue/units sold per day

Overriding Default Templates

Simply create a

directory and create a file of the same name as the template you want to replace.


has a (small) suite of tests that are run via TravisCI, but can (and should) also be tested manually once installed. Run
python app.py
and browse to http://localhost:5000/test/1. You should see a single "Buy" button, which should be completely functional (assuming you have at least one product in your database). Enter Stripe's test credit card number (4242 4242 4242 4242). You should be successfully directed to a "success.html" page with your download link. If your product is in the
directory, you'll be able to download it by clicking the link.


Don't run

in production. The web server it uses is not meant for such a purpose. Instead, deploy as you would normally deploy an WSGI application. See Flask's documentation on the subject.


Still need to add better documentation and (possibly) deployment information. All of this is coming. I just wanted to get

out as fast as possible so that those who know what they're doing can make use of it.

Bitdeli Badge

We use cookies. If you continue to browse the site, you agree to the use of cookies. For more information on our use of cookies please see our Privacy Policy.