Skip to content

Instantly share code, notes, and snippets.

@quekshuy
Created December 9, 2012 08:41
Show Gist options
  • Save quekshuy/4243901 to your computer and use it in GitHub Desktop.
Save quekshuy/4243901 to your computer and use it in GitHub Desktop.
[Advocado] Redesign Notes (for Documentation)

Here are the exact steps on how the implementation would go as of now.

##On the Product Page

  1. Product page loads. Also loads Advocado JS.
  2. Advocado JS extracts information from the page or from parameters to decide what to render.
  3. Advocado JS calls platform side API or advocado backend for data to populate templates (mustache.js).
  4. Advocado JS downloads, renders and inserts the overlays (HTML/CSS) (via templates) into the page
  5. Wait for user interaction
  6. User clicks and proceeds to choose one of the sharing channels, for the case of this scenario, Facebook
  7. Advocado JS calls sharing service in a popup, passing it some parameters. The sharing popup loads the UI for the required service. Sharing on Facebook (https://developers.facebook.com/docs/reference/dialogs/feed/)
  8. Once sharing is done, the popup redirects to our interim page which creates the share, closes the popup and redirects the parent window to the same URL, but now with some additional GET parameters.
  9. Reloading, we pull out GET parameters and load the "Add to Cart" overlay, which allows the shopper to add a discounted version of that item to the cart. The most important GET parameter is the stCode param which we will use to verify our actions. We write the stCode parameter to cookies.
  10. Once "Add to Cart" is clicked, Advocado JS calls a HTTP POST on the platform side API that allows adding of objects to the shopping cart. We pass in stCode as an argument to the call.
  11. The platform side API code will query the backend to ensure stCode is correct, before it allows the adding of the discounted item.
  12. If 200 OK, we move to the next screen and prompt user to either checkout or continue shopping.
  13. Else, we display an error.

##On the Checkout Confirmation (Thank You) Page

  1. Advcado JS loads.
  2. Advocado JS queries the backend using stCode in cookies to create a subscription.
  3. Backend returns coupon code details if coupon is created.
  4. Advocado JS displays coupon code details or prompts user to action.

Let's trash out some of the interface decisions here for the Advocado JS part of the above descriptions.

We provide 2 kinds of API objects. The first is the platform side API, which contains URL calls specific to that platform. The second is the backend API, allowing us to query the backend for Advocado's objects.

These can be called like this.

var pApi = new AdvocShopifyAPI({ 
  siteId: 234345   
});

var bApi = new AdvocBaseAPI({
   siteId: 234345,
   // combination of siteId, verify and rKey allow for authentication of the requests
   verify: 'fhsdk3837HFAs',
   rKey: 'fdkd878349hdhjfha'
});


// Fetches campaign object for local product ID 123
var campaign = bApi.campaign({productId: 123});

// adds product 123 with campaign details
pApi.addToCart({ 
    productId: 123,
    discountType: campaign.discountType,
    discountAmt: campaign.shareDiscount,
    qty: 2,
    stCode: 'djfd238734SKHF', // to go into detail about stCode later
}); 

The below is the share widget, which incorporates the overlays, etc.

// we need to provide the widget with the siteId and the productId
// in order for us to query and display the correct info
var s = new AdvocShareWidget({
    productId: 123435,
    siteId: 2837,
    platformAPI: pApi,
    baseAPI: bApi
});

// inserts HTML before the jQuery element
// does the querying for data depending on the productid
// loading is expected to be asynchronous
s.attach($('#add-to-cart-btn'));

// Event-based architecture. We listen on events and respond accordingly.
s.on('shared', function(e) { 
	// Do something when shared
});

s.on('cartAdded', function(e) { 
    // Do something when user has shared and added to cart
});

The checkout widget is what registers that a share was previously done and creates the subscription.

var cw = new AdvocCheckoutWidget({
    siteId: 3278,
    stCode: '34783KJKJF', // the stCode verifies that a share was previously completed
    platformAPI: pApi,
    baseAPI: bApi
});

// Only starts querying the backend at this point
cw.attach($('#checkout-message'));

cw.on('created', function(data) { 
 // Do something with the data 
});

We project that every framework will have its intricacies/variations in how we expose information to our widgets. Hence we introduce a loader framework, i.e. for each platform/framework, e.g. we have a custom loading module.

E.g. for Shopify

/*
   This could be //CND_HOST/advocado/shopify/loader.js for example
*/

// Module pattern
var AdvocShopify = (function($) {

    function _siteId() { 
        // return the site ID retrieved from some element on the page
    }

    function load() { 
          // calls loadShareWidget if conditions are right, e.g. it's a product page
          // else calls loadCheckoutWidget
    }

    function loadShareWidget(attachElement) {
       var siteId = _siteId();
       // include all the code that I wrote for loading the share widget
    }

    // ... other methods, e.g. loadCheckoutWidget()

    return { 
         load: load
    };

})(jQuery);

AdvocShopify.load();

##Share Transaction Codes

Since there will be instances where we will be creating objects on the backend via the Advocado JS, we will need to figure out a secure way to verify the following:

  • all chargeable objects (e.g. subscriptions) created are authentic

There is a way to do this, as our backend can act as a simple form of security gateway. How we do this is via the share transaction code (hereon to be referred as stCode).

A typical flow would be this:

  • I use the Sharing Proxy to launch Facebook in a popup window and share. The Sharing proxy then reloads the parent window, with one special GET parameter: stCode. The stCode is a UUID-like string which uniquely identifies that a Share has been completed; it should be non-sequential to time created.

  • The stCode is stored in the cookies like thus:

stMap=<productId1>,<campaignId1>,<stCode1>[|<productId2>,<campaignId2>,<stdCode2>]
  • When the user adds a discounted item to the cart (after a share), we look up the stCode from cookies and verify that the stCode exists, via a query to the backend like this:

Get a share object that has stCode and appKey and that we know has not been posted yet (isPosted=0)

GET /v2/shares/?stCode=1234&appKey=efaf78237&isPosted=0

If 200 OK and a Share object(s) is returned, we know that the share was successful.

  • When the user checks out, we can create a Subscription object using the stCode as well (in fact, we should)
POST /v2/subscriptions/

Body:
stMap=[{1,2,<stCode1>}|2,4,<stCode2>]&appKey=34783&.....

Take note that this representation for stMap may not be accurate.

  • After checkout we delete the stMap from the cookies.

###Some notes about stCode

stCode maps to a campaign.

If a user has shared for one particular product in a campaign, he/she will receive an stCode that is consistent to whatever is shared for other products in that campaign. It is up to the implementor to decide the behaviour, i.e. with one stCode for the campaign, should the user share another time for a different product from the same campaign?

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