Skip to content

Instantly share code, notes, and snippets.

@nashibao
Last active August 29, 2015 13:56
Show Gist options
  • Save nashibao/8894292 to your computer and use it in GitHub Desktop.
Save nashibao/8894292 to your computer and use it in GitHub Desktop.
How to connect karte asp api to your app.

How to connect karte api to your app

  1. request for creating(updating) a project(per store) in karte
  2. embed js code in html header
  • [APP_PUBLIC_KEY] & [APP_PRIVATE_KEY] would be sent from karte.io per app.

1. request for creating(updating) a project in karte

request(get) format:

https://karte.io/asp/api/0.1/create?key=[APP_PUBLIC_KEY]&email=store@example.com&store_id=store_id&time=[UNIX TIMESTAMP]&enable=true&signature=[SIGNATURE]
  • signature is a HMAC token with sha256. How to create a signature param is described in the sample code.
  • for updating enable parameter, you should change create to update in request url.

response format:

  {
    "message": "an account was created successfully.",
    "email": "[email protected]",
    "store_id": "store_id",
    "enable": False,
    "api_key": "[STORE_API_KEY]"
  }

sample code by python:

import unittest

from time import time
import hmac
import hashlib
import urllib2
import json

class TestKarteAspApi(unittest.TestCase):

  """
  setup
  """
  def setUp(self):
    self.url_base = "https://karte.io/asp/api/0.1/"

    self.private_key = "[APP_PRIVATE_KEY]"
    self.public_key = "[APP_PUBLIC_KEY]"


  """
  util function: create hmac signature by sha256
  """
  def create_signature(self, key, email, store_id, time, enable, private_key):
    data = "key=%s&email=%s&store_id=%s&time=%d&enable=%s" % (key, email, store_id, time, "true" if enable else "false")
    sig = hmac.new(private_key, data, hashlib.sha256).hexdigest()
    return sig

  def test_karte_api(self):

    print 'test karte api start --------'

    # url ---------------------
    url = self.url_base + "create"
	# for updating `enable` parameter, only changing the url is needed.
    # url = self.url_base + "update"

    # parameters ---------------------
    key = self.public_key
    email = "[email protected]"
    store_id = "store_id"
    t = int(time())
    enable = False
    sig = self.create_signature(key, email, store_id, t, enable, self.private_key)
    
    # encode params
    email = urllib2.quote(email)
    
    # get ---------------------
    data = "?key=%s&email=%s&store_id=%s&time=%d&enable=%s&signature=%s" % (key, email, store_id, t, "true" if enable else "false", sig)
    
    try:
      res = json.loads(urllib2.urlopen(url + data).read())
    except urllib2.URLError, e:
      print "error code = %s" % e.code # != 200
      raise e
    else:
      # == 200
      print "get 200"


    # assertion ---------------------
    self.assertIsNotNone(res['api_key'])
	
	# App must store this 'api_key' per store to embed js in header.

2. embed js code in html header

2.1 (required) embed the common code

The below code must be embeded in all html header where you would like to send any data.

  • [STORE_API_KEY] is the token which you get in chapter 1.
<script type="text/javascript">
!function(){var a;a=a||[],function(){var b,c,d,e;for(c=["identify","track"],b=function(b){return function(){return a.push([b].concat(Array.prototype.slice.call(arguments,0)))}},d=0,e=[];d<c.length;)a[c[d]]=b(c[d]),e.push(d++);return e}(),a.init=function(b,c){var d,e;return a.api_key=b,a.options=c||{},a.options.tracking_url="https://karte.io",e=document.createElement("script"),e.type="text/javascript",e.async=!0,e.src="https://karte.io/libs/tracker.js",d=document.getElementsByTagName("script")[0],d.parentNode.insertBefore(e,d)},a.Date=function(){function a(a){this.name="trackerDate",this.source=a}return a}(),window.tracker=a}.call(this);
tracker.init("[STORE_API_KEY]");
</script>

2.2 (recommended) identify: send user data

The code should be embeded in a html header if user is logging in.

For example you should put it in a login page or an account setting page.

<script type="text/javascript">
	
    tracker.identify({
    	// 1. required -----------------------
    	user_id: "user_unique_id",
	
    	// 2. recommended -----------------------
    	email: "[email protected]",
    	subscription: false,
    	name: 'kobayashi hiroki',
    	create_date: new Date("2012/12/01"),

    	// 3. options -----------------------
    	// conversion stats
    	buy_times: 10,
    	buy_total: 100,
    	last_buy_date: new Date("2012/12/01"),
    	
    	// you can send any data like below
    	point: 100,
    	gender: 'F',
    	birth: new Date('1982/09/19'),
    	tel: '000000000',
    	zip: "000",
    	country: "japan",
    	pref: "tokyo",
    	address: "shibuya shoto 2"
  });
</script>

2.3 (recommended) buy: send conversion events

You should embed conversion code in a thanks page.

<script type="text/javascript">
	var items = [
    	{
    		// required -----------------------
      		item_id: "item_unique_id",
      		name: "item name",
      		price: 100,
      		quantity: 1,
    		// recommended -----------------------
      		category: ["category1", "category2"]
    	}
  	];
  	tracker.track('buy', {
    		// required -----------------------
    		transaction_id: "transaction_unique_id",
    		revenue: 1000,
    		items: items,
    		// recommended -----------------------
    		shipping: 100,
    		tax: 10
  	});
</script>

2.4 (option) send any events

You can send any custom events like below.

<script type="text/javascript">
  	tracker.track('upgrade_plan', {
		plan: 'gold'
  	});
</script>
@nashibao
Copy link
Author

nashibao commented Mar 3, 2014

Also, in the karte admin, it appears loading/refreshing https://karte.io/group with "real time" selected makes the counter display 1 when there are none. Clicking to see the users doesn't show any results. Switching to another option and back again to real time returns it to 0.

Thanks! I registered the bug to our bug tracking.

@nashibao
Copy link
Author

nashibao commented Mar 3, 2014

Is tracker.identify(...) and the user_id truly required? If so is it best for us to have the user_id be the same for all customers?
We have a plan to make Karte a product which can be used without the user_id(only with a session-id).
But currently Karte requires the user_id for all sending data.

We will talk to the agency today about the problem (and schedule for non-logged-in users).

@nashibao
Copy link
Author

@bcoon
I just updated the code which doesn't require the user_id. Then you can send identify events only when you would like to send.

Thanks.

@nashibao
Copy link
Author

And I minified the tracking code https://karte.io/libs/tracker.js to one third.
If you still have some trouble to load tracker.js, please tell me.

(It's recommended to use the code 2.2 for loading tracker.js, because the code loads tracker.js asynchronousely (no blocking other components) and does some preparation for tracking..
But, off course you can use your favorite loaders as require.js.)

@bcoon
Copy link

bcoon commented Mar 20, 2014

Thank you for the updates.

I will likely resume work on Karte integration fairly soon.

@bcoon
Copy link

bcoon commented Apr 1, 2014

Hi,

I'm finally able to get back to testing Karte integration, but I believe I found an oversight:

Having a '+' in an email address is valid, but I received a validation error when testing. It just so happened that my email for my test Goodsie account has a plus sign in it. The email address "[email protected]" failed validation from Karte. After concluding that was the cause of my validation problem, I changed my email address and went to try again, but had my connection refused due to a max retries issue: http://cl.ly/image/2L1L2x0S0P0X
I'll wait and try again with a 'valid' email address for now.

@nashibao
Copy link
Author

nashibao commented Apr 1, 2014

@bcoon
I will check the validation of email now. Please wait for a while.

@nashibao
Copy link
Author

nashibao commented Apr 2, 2014

@bcoon
I deleted the validation of email from it.
And I added urllib2.quote to the test code of python. ref: https://gist.github.com/nashibao/8894292/revisions
Could you resume the test again?
Thanks!

@bcoon
Copy link

bcoon commented Apr 2, 2014

Hi again,

I was able to obtain an existing api key using an email with no plus sign (without urllib2.quote). Using urllib2.quote is returning 'This signature couldn't be authorized.' both with and without using a plus sign in the email address.
Does this work for you? I'm wondering if there is a decoding issue somewhere.

'[email protected]' encodes to 'brian%2B4%40goodsie.com'

Trying to create a Karte account with a new test email address, '[email protected]', returns "cannot create account."
Thoughts?

Thanks!

@nashibao
Copy link
Author

nashibao commented Apr 3, 2014

Sorry I'm very late..

Did you encode a email before creating a signature? I think the error ''This signature...' may be caused by it.

@nashibao
Copy link
Author

nashibao commented Apr 3, 2014

And if you send a same store_id with different email address, "cannot create account." error would be caused.
The reason of second problem may be it.

Thanks!

@nashibao
Copy link
Author

nashibao commented Apr 3, 2014

Could you send me a direct message to twitter(https://twitter.com/nashibao)? because the threads of gist.github.com can't notify me new messages.

@bcoon
Copy link

bcoon commented Apr 3, 2014

Okay, so, we're stuck.
When loading the tracker.js script via the snippet posted above, we get http://cl.ly/image/302Z1i2S1I1t

Once in a rare while, it appears to load fine the first time I load my site, then refreshing gets me this:
http://cl.ly/image/3T1i0I1m1q1Q

Hitting 'enter' in the address bar again gets me that first error again.

While we are using requireJS for other script loading, tracker.js is being loaded in the recommended manner.

When trying to load the script via requireJS I end up with this: http://cl.ly/image/0G051k213432
I'm not sure whose code is causing that to happen, I could be missing something, but I'm out of ideas.

Do you have any idea what could be happening here? We're running out of ideas.

Also, what library does the require definition at the top of tracker.js belong to? We were at first thinking there was a conflict with that object name and requireJS's 'require', but I downloaded tracker.js and tried loading it with a different named object. That didn't do anything unfortunately.

Thanks,
Brian

@nashibao
Copy link
Author

nashibao commented Apr 3, 2014

what library does the require definition at the top of tracker.js belong to?

tracker.js uses component as a module loader.
I thought that It wouldn't conflict with other module loaders, but the error seems to be caused by the conflict.
I'm sorry I didn't check the conflict with other loaders.

I will check it today. Please wait a while..

@nashibao
Copy link
Author

nashibao commented Apr 4, 2014

I found the conflict between component (exactrly component/lodash) and requirejs. I modified and updated tracker.js a little while ago.
Could you resume the testing?

Thanks.

@bcoon
Copy link

bcoon commented Apr 9, 2014

Couple last questions:

Can these event names all be safely translated to Japanese? http://cl.ly/image/44323h2V0K3b
'buy' and 'view' are reserved, correct?

Since our storeowners are anonymous - they don't have an account - will this total always be one? http://cl.ly/image/0a292U3z021L

I believe I have what should be a working 'buy' event, but I haven't seen the results of it in the admin yet.
I'm passing the parameters as expected (numbers when applicable).
The Request URL looks like this https://karte.io/track?d=%7B%222%22%3A1397073049%2C%223%22%3A%2256a999fa0d0177f132fe26fd2f679ec2%22%2C%226%22%3A%223229071115_1397071911530_714794875%22%2C%227%22%3A%223229071115_1397071911530_714794875_1%22%2C%228%22%3A%22%2Fthanks%22%2C%229%22%3A%22brian-dev.goodsie.dev%22%2C%22a%22%3A%22Mac%20OS%20X%22%2C%22b%22%3A%2210.9.2%22%2C%22c%22%3A%22Mac%20OS%20X%2F10.9.2%22%2C%22d%22%3A%22WebKit%22%2C%22e%22%3A%22537.36%22%2C%22f%22%3A%22Chrome%22%2C%22g%22%3A%2233.0.1750.152%22%2C%22h%22%3A%2233%22%2C%22i%22%3A%22Chrome%2F33.0.1750.152%22%2C%22j%22%3A%22en-us%22%2C%22k%22%3A1436%2C%22l%22%3A878%2C%22m%22%3A22%2C%22n%22%3A4%2C%22o%22%3A24%2C%22p%22%3A24%2C%22q%22%3A1440%2C%22r%22%3A900%2C%22E%22%3A%22http%22%2C%22F%22%3A%22brian-dev.goodsie.dev%22%2C%22G%22%3A%22%2Fthanks%22%2C%22H%22%3A%22%22%2C%22I%22%3A%22Thanks%20%7C%20brian-dev%22%2C%22w%22%3A%22http%22%2C%22x%22%3A%22brian-dev.goodsie.dev%22%2C%22y%22%3A%22%2Fcheckout%22%2C%22z%22%3A%22%22%2C%22events%22%3A%5B%7B%22event_name%22%3A%22buy%22%2C%22values%22%3A%7B%22transaction_id%22%3A%221051%22%2C%22revenue%22%3A0.95%2C%22items%22%3A%5B%7B%22item_id%22%3A%22apple%22%2C%22name%22%3A%22unlimited%22%2C%22price%22%3A0.95%2C%22quantity%22%3A1%2C%22category%22%3A%5B%22%22%5D%7D%5D%2C%22shipping%22%3A0%2C%22tax%22%3A0%7D%7D%5D%7D&callback=jsonp2
which looks alright when decoded.
My admin isn't showing any items purchased though - http://cl.ly/image/1c3z3I312R1Q

Thanks for all the help.

@nashibao
Copy link
Author

nashibao commented Apr 9, 2014

Can these event names all be safely translated to Japanese? http://cl.ly/image/44323h2V0K3b

No. These events are not translated.

'buy' and 'view' are reserved, correct?

Yes!

Since our storeowners are anonymous - they don't have an account - will this total always be one?
I believe I have what should be a working 'buy' event, but I haven't seen the results of it in the admin yet.

Please change the 'user' to 'visitor in the right-up select box.

1.png
2.png
3.png

I think these events are correctly sended and analyzed.

I'm sorry for a lack of 'help' which explains 'users' and 'visitors' . I think Karte should change admin page to 'visitor' when 'anonymous' visitors only be captured..

@nashibao
Copy link
Author

nashibao commented Apr 9, 2014

'user' means the people who has 'user_id', 'visitor' are the opposite.

Since our storeowners are anonymous - they don't have an account - will this total always be one?

Does it mean people who visited the e-commerce site to buy something??

@bcoon
Copy link

bcoon commented Apr 9, 2014

Since our storeowners are anonymous - they don't have an account - will this total always be one?
I meant to say that our customers don't have an account. Yes sorry. Thanks for the updates.

Can these event names all be safely translated to Japanese? http://cl.ly/image/44323h2V0K3b
I'd like to clarify, so I'll reword my question a bit:
So we should keep all the custom events in English and they'll appear in the admin as English? Or are we able to translate to Japanese?

@nashibao
Copy link
Author

nashibao commented Apr 9, 2014

So we should keep all the custom events in English and they'll appear in the admin as English? Or are we able to translate to Japanese?

You should keep it in english and Karte can't translate it now.
But I can fix it to translate the reserved event's names (including events which ASPs always send to karte).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment