Protecting Your Product

An important part of being successful as a digital product vendor is taking precautions to protect your product and keep it from being improperly downloaded. In this guide, we have several steps you can take to keep your product secure.

The following subjects are covered in this article:

General Guidance

To protect your product, here are some suggestions:

  • If your product is a one-time digital product, see the Digital Product Upload article for information about having ClickBank deliver your product to customers.
  • Add the following HTML code in the <HEAD> element of your Thank You Page should prevent a search engine robot from indexing that page or following links on that page:
    <META name="robots" content="noindex, nofollow"/>
  • Give your Thank You Page URL an obscure file name (it should not be something like thankyou.htm, which is too easy to guess).
  • Consider using a third party solution. Popular third parties include DLGuard and WishList.
  • If you are concerned about security and you have experience with CGI programming, you can generate a script that will verify the customer’s successful completion of the purchase process before allowing him or her access to the Thank You Page. Follow the instructions below for implementing the ClickBank Link Security Script.

Using a Link Security Script

When the customer completes a purchase, several values are passed along to your thank you page in the query string if you have specified a secret key in your account settings. These are the ClickBank receipt number (cbreceipt), the epoch time of the order (time), the ClickBank item number (item), and the ClickBank proof of purchase (cbpop) value.

During the purchase we encrypt the receipt, time, and item using the secret key you specify in your account. We will then pass the result back to you as a query string parameter called cbpop. Use the validation script to confirm the cbpop value is correct.

Unlike prior versions of this script there is no need for a “seed” value.

The C#, VB.NET, and Ruby examples below are only a method for checking for a valid cbpop value and leave the capturing of the request parameters up to your individual implementations.

Code Samples

PHP Source:

function cbValid(){
  if ($cbpop==$xxpop){
  return 1;
  else {
  return 0;

Perl Source:

sub cbValid
{ my($q,$key,$rcpt,$time,$item,$cbpop,$xxpop) 

  $q=~/Wcbreceipt=(w+)/; $rcpt=$1 
  $q=~/Wtime=(w+)/;      $time=$1 
  $q=~/Witem=(w+)/;      $item=$1 
  $q=~/Wcbpop=(w+)/;     $cbpop=$1 

  use Digest::SHA1 qw(sha1_hex) 
  return 1 if $cbpop eq $xxpop 
  return 0 

C# Source:

public bool cbValid(string cbreceipt, string time, string item, string cbpop)
    string secret_key = "YOUR SECRET KEY" 

    byte[] data = Encoding.Default.GetBytes(secret_key + "|" + cbreceipt + "|" + time + "|" + item) 
    byte[] hashedData = new SHA1Managed().ComputeHash(data) 

    string xxpop = BitConverter.ToString(hashedData).Replace("-","").ToUpper().Substring(0, 8) 

    return cbpop.Equals(xxpop) 

VB.NET Source:

Public Function cbValid(ByVal receipt As String, ByVal time As String, ByVal item AsString, ByVal cbpop As String) As Boolean
    Dim key As String = "YOUR SECRET KEY"
    Dim sha As New SHA1CryptoServiceProvider()
    Dim mash As String = key &amp; "|" &amp; receipt &amp; "|" &amp; time &amp; "|" &amp; item

    Dim result() As Byte = sha.ComputeHash(NewSystem.Text.ASCIIEncoding().GetBytes(mash))

    Dim xxpop As String = BitConverter.ToString(result).Replace("-","").ToUpper().Substring(0, 8)

    Return cbpop.Equals(xxpop)
End Function

Ruby Source:

require 'digest/sha1'

def cbValid(receipt, time, item, cbpop)

  popCheck = "#{key}|#{receipt}|#{time}|#{item}"
  xxpop = Digest::SHA1.hexdigest(popCheck).upcase[0,8]

  cbpop == xxpop

Python Source:

import hashlib

def valid_cb_pop(receipt, time, item, cbpop):
    secret_key = 'YOUR SECRET KEY'
    data = "%s|%s|%s|%s" % (secret_key, receipt, time, item)
    return cbpop == hashlib.sha1(data).hexdigest()[:8].upper()

Java Source:

import org.apache.commons.codec.digest.DigestUtils 

* Note:  To make this method simple it uses the Apache Commons Codec library for computing the SHA value.
*        This library is available at:

public class CBPopValidator {

     * Code to validate cbpop parameter passed from ClickBank orderform to thank-you page.
     * @param receipt The receipt number that ClickBank generated and passed to thank-you page.
     * @param time The time (unix timestamp) of the purchase, also passed to thank-you page
     * @param item The item purchased, also passed to thank-you page
     * @param cbpop The passed validation parameter
     * @return True of passed cbpop matches the calculated cbpop using the passed parameters and secret key
    public static boolean validCbPop(final String receipt, final String time, final String item, final String cbpop) {
        // secret key on the site of your ClickBank account
        final String secretKey = "YOUR SECRET KEY" 

        // create sha1 of passed data with secret key
        String hashedData = DigestUtils.shaHex(String.format("%s|%s|%s|%s", secretKey, receipt, time, item)) 

        // compare hashed result to passed value
        return hashedData != null &amp;&amp; hashedData.substring(0,8).equalsIgnoreCase(cbpop) 
Have more questions? Submit a request


Please sign in to leave a comment.
Powered by Zendesk