NAV

Introduction

Welcome to the Ramen Developer Documentation.

FAQ

How do I install RamenJS?

There are several ways to install RamenJS into your application:

What platforms do you support?

RamenJS can be installed into any web application, although using it with a Flash application would be tough :)

Here are some of the platforms we’ve seen install RamenJS:

Does RamenJS work on “Single Page Apps”?

Yes it does. See our Examples section.

Installation

Segment.com

Segment.com is a “customer data hub”. If you already are a Segment customer, you can install Ramen in just a few clicks without needing to write any code or deploy any changes to your application.

RamenJS supports the following Segment methods:

Installation methods

Click the ‘Install via Segment’ button on the Getting Started page of your Ramen Organization.

Wait a couple minutes, and then head over to your application and navigate to a page where Segment’s analytics.js is installed. After refreshing the page a few times, refresh this page and you should see that RamenJS is receiving data.

Enable Secure Mode (Optional)

Once you’ve verified Ramen is enabled, you may want to enable Secure Mode.

Secure Mode ensures that nobody can pretend to be your customers. Enabling Secure Mode requires some changes that a developer will have to make in your Segment.com analytics.js code.

Click here to view the Segment.com / Ramen Secure Mode Documentation

Learn More About Segment.com

To learn more about Segment, click here

Eager.io

Eager.io lets you install JavaScript libraries at the touch of a button. If you are already using Eager, you can install Ramen in just a few clicks without needing to write any code or deploy any changes to your application. If not, we strongly recommend looking into it, because it is awesome.

Installation methods

Click the ‘Install via Eager’ button on the Getting Started page of your Ramen Organization.

Wait a couple minutes, and then head over to your application and navigate to a page where Eager is loaded. After refreshing the page a few times, refresh this page and you should see that RamenJS is receiving data.

Learn More About Eager.io

To learn more about Eager, click here

Ruby on Rails Rubygem

Ramen maintains an official Rubygem for Ruby on Rails applications. The Rubygem is used on Ramen.is itself.

View the Rubygem

Wordpress

Thanks to our integration with Eager, installing RamenJS on Wordpress is a breeze.

Installation methods

Click the ‘Install via Eager’ button on the Getting Started page of your Ramen Organization.

When you are prompted, download and install the Wordpress plugin from Eager.

Wait a couple minutes, and then head over to your application and navigate to a page where Eager is loaded. After refreshing the page a few times, refresh this page and you should see that RamenJS is receiving data.

Drupal

Thanks to our integration with Eager, installing RamenJS on Drupal is a breeze.

Installation methods

Click the ‘Install via Eager’ button on the Getting Started page of your Ramen Organization.

When you are prompted, download and install the Drupal plugin from Eager.

Wait a couple minutes, and then head over to your application and navigate to a page where Eager is loaded. After refreshing the page a few times, refresh this page and you should see that RamenJS is receiving data.

Joomla

Thanks to our integration with Eager, installing RamenJS on Joomla is a breeze.

Installation methods

Click the ‘Install via Eager’ button on the Getting Started page of your Ramen Organization.

When you are prompted, download and install the Joomla plugin from Eager.

Wait a couple minutes, and then head over to your application and navigate to a page where Eager is loaded. After refreshing the page a few times, refresh this page and you should see that RamenJS is receiving data.

Angular

While there is no official library for Angular, we do have an Example App

Pay close attention to the comments on the commits to see what is going on: Commits

Concepts

Boostrapping

Getting RamenJS installed into your application requires two bits of code.

<script>
  window.ramenSettings = {
    organization_id: "lkadjf89383hr89",
    user: {
      id: "903849h",
      name: "Bugs Bunny",
      email: "ryan+bugs@ramen.is"
    }
  };
</script>

<script src="https://cdn.ramen.is/assets/ramen.js" async></script>

First, you need to define the window.ramenSettings object.

Then, you need to include the RamenJS library.

The order of operations is important here. window.ramenSettings must be defined before RamenJS is loaded.

Custom installation

<script src="https://cdn.ramen.is/assets/ramen.js" async></script>

<!-- Later... -->

<script>
  $(function() { // See note
    Ramen.init.update({
      organization_id: "lkadjf89383hr89",
      user: {
        id: "903849h",
        name: "Bugs Bunny",
        email: "ryan+bugs@ramen.is"
      }
    });
  });
</script>

For some more complicated apps, you may not want to, or be able to, define ramenSettings at the time the page renders.

In that case, load the RamenJS script tag as shown.

Later on, you can call Ramen.init.update after the page has completely loaded.

A note on order of operations

Note that calls to anything under the Ramen object need to be wrapped in some sort of onReady callback

This is an issue we’ll be addressing with RamenJS v2.0, which will ship in the first half of 2016.

Secure Mode

Secure Mode ensures that nobody can spoof being one of your customers. It is disabled by default, because it takes a little extra developer time to setup correcgtly.

To enable secure mode, you need to add a few things to your ramenSettings object:

Timestamp

ts = Time.now.to_i
ts = Math.floor(new Date()) / 1000)

The timestamp attribute must be a time within the last 15 minutes.

Calculating auth_hash

array = []
array << "ryan@ramen.is"
array << 42
array << "Ryan Angilly"
array << 1234567890
array << "oihs9uhasdg8934y8"
str = array.join(":")
digest = (Digest::SHA256.new << str).to_s
digest #=> "09cc0a69233f1bf41e68ed00b9256fde5a4542e9fdba635fe2a9a4edf9ee1ba1"

The hash is calculated as follows:

  1. Create an array with the following elements:

    • email: eg. "ryan@ramen.is"
    • id: eg. 42
    • name: eg. Ryan Angilly
    • timestamp: eg. 1234567890
    • ORGANIZATION_SECRET_KEY: eg. oihs9uhasdg8934y8
  2. Your array now looks like this: ["ryan@ramen.is", 42, "Ryan Angilly", 1234567890, "oihs9uhasdg8934y8"

  3. Join the elements of that array together with a colon (:) into a string

  4. Your string is now: "ryan@ramen.is:42:Ryan Angilly:1234567890:oihs9uhasdg8934y8"

  5. Generate a SHA256 hash from that string

  6. The SHA256 hash for the string in step 4 is: 09cc0a69233f1bf41e68ed00b9256fde5a4542e9fdba635fe2a9a4edf9ee1ba1

Customers

<script>
  window.ramenSettings = {
    organization_id: "lkadjf89383hr89",
    user: {
      id: "903849h",
      name: "Bugs Bunny",
      email: "ryan+bugs@ramen.is"
    }
  };
</script>

Ramen is used for asking questions, but only of your users. This means that until a User has logged into your app, there is no way Ramen will be able to interact with them.

In Ramen terminology, a we call a person logged into you application a ‘Customer’.

RamenJS must know the following things about your customers:

Attribute Type Required Notes
id String Yes A unique identifier
email String Yes A valid email address
name String Yes The name of the person

In additional, ramenSettings also accepts the following options:

Attribute Type Required Notes
created_at Integer No The unix timestamp (epoch seconds, not milliseconds) for when this account was created.
value Float No An arbitrary value for that person. Used for Audience creation.
traits Object No See Custom Traits below
bug_image_url String No URL for an image to replace the standard green Ramen ‘R’ icon. See Customization below.
question_id String No The ID of a question. This will forces a specific question to appear no matter what.

Companies

<script>
  window.ramenSettings = {
    organization_id: "83hakj3",
    user: { /* Explained above */ },
    company: {
      id: "42",
      name: "Ramen",
      url: "https://ramen.is"
      value: 353000.0,
      traits: {
        is_rad: true
      }
    }
  };
</script>

You can group a Customer into a Company. A Company is an organization that the currently logged in person belongs to.

Company data can be used when creating Audiences. So you could, for example, target a question to only appear to Customers that are members of a specific Company.

RamenJS wants to know the following things about Companies:

Attribute Type Required Notes
id String Yes A unique identifier
url String Yes A valid URL for the comapny
name String Yes The name of the company
value Float No An arbitrary value for that company. Used for Audience creation.
traits Object No See Custom Traits below

Custom Traits

<script>
  window.ramenSettings = {
    organization_id: "iafh89335",
    user: { /* Explained above */ },
    company: {
      id: "42",
      name: "Ramen",
      url: "https://ramen.is"
      value: 353000.0,
      traits: {
        is_rad: true,
        funded_at: 1234567890
      }
    }
  };
</script>

Both Customers and Companies can have “Traits” assigned to them. Traits are key/value pairs that can be used for Audience creation:

Traits can be used to create Audiences

Names

Trait names are strings that can contain any letter, any number, underscores (_) and dashes (-). Trait names are case-sensitive.

Types

Trait values can be the following types:

Time types

Time types are declared by ending the trait name in _at. For example:

You can pass in times in the following formats:

Type Casting

The first time RamenJS sees a new trait with a non-null value, it will record the type and cast all future traits to that type.

Customization

Icon

<script>
  window.ramenSettings = {
    organization_id: "lkadjf89383hr89",
    user: {
      id: "903849h",
      name: "Bugs Bunny",
      email: "ryan+bugs@ramen.is",
      bug_image_url: "https://thecatapi.com/api/images/get?format=src"
    }
  };
</script>

The RamenJS popups were designed to be minimal so that they would Just Look Good™ on any webpage. The style of the popups cannot be modified, but the icon, the little green Ramen ‘R’ can be chanaged.

Product Center

Product Center is a feature that lets you discuss Features with your Customers. Product Center is only available on certain paid plans.

<script>
  window.ramenSettings = {
    organization_id: "...",
    user: { /* Explained above */ },
    company: { /* Explained above */ },
    custom_links: [
      {
        title: 'E-mail support',
        href: 'mailto:support@ramen.is',
      },

      {
        title: 'Chat with support',
        callback: 'Interom("showNewMessage")'
      } /* This is not a type. If you want to use
           Intercom for in-app chat, this is one way
           to make it play nice w/ Ramen. */
    ]
  };
</script>

We provide a way for you to customize links that appear at the bottom of Product Center.

Custom Links have a title property and either an href or a callback property. hrefs must be full URIs (including protocol, ie. https). callbacks can be JavaScript closures or strings that will be eval’d

You are allowed to provide up to 3 Custom Links.

Placement

<nav>
<ul>
  <li><a href="/account">Your Account</a></li>
  <li><a href="/product-center" id="custom-ramen-trigger">Product Center</a></li>
</ul>
</nav>

<style>
._r-badge:after {
  top: -5px;
  right: -5px;
  background-color: red;
  -webkit-border-radius: 100px;
  -moz-border-radius: 100px;
  border-radius: 100px;
  content: " ";
  height: 18px;
  width: 18px;
  position: absolute;
  font-size: 12px;
  line-height: 16px; 
}

._r-related {
  font-weight: bold;
}
</style>

<script>
window.ramenSettings = {
  organization_id: YOUR_ORG_ID,
  user: {...},
  company: {...},
  custom_trigger_id: "custom-ramen-trigger"
};
</script>

You can set a custom placement, called a ‘trigger’ for the RamenJS widget so that instead of showing the icon in the bottom right or left corner of the screen, a link in your nav can be used to trigger opening Product Center.

To enable this customization, set ramenSettings.custom_trigger_id to the ID of the element.

Styling the Custom Trigger

We apply different styles to the RamenJS widget:

  1. When there is a Feature related to the current URL, the widget icon will be full color.
  2. When there are no related features, a grayscale image is used instead.
  3. When there are newly deployed features, a circular red badge is placed over the top right corner of the icon.

When using a customer trigger, we do not attempt to modify the style to reflect state changes. Instead, we will add classes to the element. It will be up to you to style the elements.

Examples

Here are some heavily commented examples.

Ruby/ERB

If you’re on Ruby on Rails, you should check out our Rubygem, but if not, here is a Ruby/ERB example.

<!-- 1. OPTIONAL: This <link> tag can goes at the top of your <head> to prefetch DNS -->
<link rel="dns-prefetch" href="http://cdn.ramen.dev">

<!-- 2. This script tag can go anywhere in the <body> but **before** the RamenJS tag -->
<script>
  <% @ts = Time.now.to_i %> <!-- Optional unless you want to use Secure Mode -->
  window.ramenSettings = {
    organization_id: "ORGANIZATION_ID",
    user: {
      // Required. If you don't have a name, pass in their email here.
      name: <%= current_user.name.to_json.html_safe %>,

      // Required. If you don't have email addresses for your logged in users, please contact support@ramen.is
      email: <%= current_user.email.to_json.html_safe %>,

      // Required. This must be unique. Changing this creates a new Customer.
      id: <%= current_user.id.to_s.to_json.html_safe %>,

      // Optional
      created_at: <%= current_user.created_at.to_i %>
    } // If you uncomment the optional attributes below, don't forget to add a comma (",") here

    // The next two keys are optional unless you want to enable Secure Mode
    // timestamp: <%= @ts %>,    
    // auth_hash: <%= (Digest::SHA2.new << "#{current_user.email}:#{current_user.id}:#{current_user.name}:#{@ts}:ORGANIZATION_SECRET_KEY").to_s.to_json.html_safe %>
  };
</script>

<!-- 3. This goes just before the closing </body> tag and **always after** where you set window.ramenSettings -->
<script src="http://cdn.ramen.dev/assets/ramen.js" async>
</script>

JavaScript

<!-- 1. OPTIONAL: This <link> tag can goes at the top of your <head> to prefetch DNS -->
<link rel="dns-prefetch" href="https://cdn.ramen.is">

<!-- 2. This script tag can go anywhere in the <body> but **before** the RamenJS tag -->
<script>
  window.ramenSettings = {
    organization_id: "YOUR_ORGANIZATION_ID",
    user: {
      // Required. If you don't have a name, pass in their email here.
      name: "Ryan Angilly",

      // Required. If you don't have email addresses for your logged in users,
      // please contact support@ramen.is
      email: "ryan@ramen.is",

      // Required. This must be unique. Changing this creates a new Customer.
      id: "527de734763a556882001003",

      // Optional
      created_at: 1234567890 
    } // If you uncomment the optional attributes below, don't forget to add a comma (",") here

    // The next two keys are optional unless you want to enable Secure Mode
    // timestamp: ts_used_server_side_to_calculate_auth_hash,
    // auth_hash: auth_hash_calculated_server_side
  };
</script>

<!-- 3. This goes just before the closing </body> tag and **always after** where you set window.ramenSettings -->
<script src="https://ramen.is/assets/ramen.js" async>
</script>

Wordpress/PHP

If you’re on Wordpress, you should checkout our Eager.io integration, but here is an example:

<!-- 1. OPTIONAL: This <link> tag can goes at the top of your <head> to prefetch DNS -->
<link rel="dns-prefetch" href="http://cdn.ramen.dev">

<!-- 2. This script tag can go anywhere in the <body> but **before** the RamenJS tag -->
<?php if ( is_user_logged_in() ) { ?>

<?php global $current_user;
  get_currentuserinfo();
  $user_roles = $current_user->roles;
  $user_role = array_shift($user_roles);

  // The next two keys are optional unless you want to enable Secure Mode
  $_ramen_ts = time();
  $_ramen_items = array($current_user->user_email, $current_user->ID, $current_user->display_name, $_ramen_ts, "ORGANIZATION_SECRET_KEY");
?>

<script>
  window.ramenSettings = {
    organization_id: "ORGANIZATION_ID",
    user: {
      // Required. If you don't have a name, pass in their email here.
      name: "<?php echo $current_user->display_name; ?>",

      // Required. If you don't have email addresses for your logged in users, please contact support@ramen.is
      email: "<?php echo $current_user->user_email; ?>", 

      // Required. This must be unique. Changing this creates a new Customer.
      id: <?php echo $current_user->ID; ?> ,

      // Optional
      created_at: <?php echo $current_user->created_at; ?>
    } // If you uncomment the optional attributes below, don't forget to add a comma (",") here

    // The next two keys are optional unless you want to enable Secure Mode
    // timestamp: <?php echo $_ramen_ts ?>,
    // auth_hash: "<?php echo hash("sha256", implode(":", $_ramen_items)); ?>"
  };
</script>
<?php } ?> 


<!-- 3. This goes just before the closing </body> tag and **always after** where you set window.ramenSettings -->
<script src="http://cdn.ramen.dev/assets/ramen.js" async>
</script>

Python

Thanks to fjania for putting this together. Gist available here

import hashlib
import time

def ramen(request):
    ramen_js = '';
    if not request.user.is_anonymous():
        email = request.user.email
        user_id = request.user.id
        name = "{} {}".format(request.user.first_name, request.user.last_name)
        timestamp = int(time.time())
        secret_key = "SECRET_KEY_GOES_HERE"
        auth_input = "{}:{}:{}:{}:{}".format(
            email,
            user_id,
            name,
            timestamp,
            secret_key,
        )
        auth_hash = hashlib.sha256(auth_input).hexdigest()

        ramen_js = '''
        <!-- This can go anywhere before the ramen.js tag -->
        <script>
            window.ramenSettings = {{
                organization_id: "555cc17077656204242f0000",
                user: {{
                    name: "{name}",
                    email: "{email}",
                    id: "{id}",
                }},
                timestamp: {timestamp},
                auth_hash: "{auth_hash}"
            }};
        </script>
        <!-- This goes before the </body> tag -->
        <script src="https://cdn.ramen.is/assets/ramen.js" async>
        </script>
        '''.format(
            name = name,
            id = user_id,
            email = email,
            timestamp = timestamp,
            auth_hash = auth_hash,
        )

    return { 'ramen_js': ramen_js }

Reference

window.ramenSettings

All the options you can set on ramenSettings, the same object you can pass to Ramen.Api.update(config) for subsequent updates.

window.ramenSettings = {
  /*
   * Core Options
   */
  // Your Organization ID
  // Required
  organization_id: "",

  // The currently logged in user
  // Required
  user: {
  },

  // The company of the currently logged in user
  company: {
  },

  // Environment. Defaults to production. If you set this
  // to anything other than 'production' then you can use
  // Secure Mode but it will not be forced on. This way
  // You can test it in Development, Staging, etc... before
  // deploying
  // Default: "production"
  environment: "production",




  /*
   * Secure Mode Options
   * Secure Mode is disabled by default. Once enabled, it
   * cannot be turned off.
   */
  // Options for Secure Mode
  ts: 1234567890,
  auth_hash: "mumbo-jumbo",




  /*
   * Misc Options
   */
  // Disables watching `window.location`, and automatically calling
  // .page() when a change (include anchor changes) are noticed.
  // Default: false
  disable_location_watch: false,

  // The ID of a Question you want to force ask
  // Default: null
  question_id: "string-id-of-question",


  // Make RamenJS not log to console
  // Default: false
  silent: false,




  /*
   * Product Center Options
   */
  // Custom Trigger Element
  customer_trigger_id: "el-id",

  // Custom Links
  custom_links: [
  ]

};

Ramen.Api.update(config)

config = {
  user: {
    id: '34349853',
    name: 'Marky Marcus',
    email: 'ryan+marky@ramen.is'
  }
};

Ramen.Api.update(config);

This updates the data for the currently logged in user.

Ramen.Api.track(event_name)

<a href="/unsubscribe" onclick="Ramen.Api.track('Clicked Unsubscribe Link');">
I'm out.
</a>

You can track events using Ramen.Api.track(event_name) and then use that data in Audience creation.

For example, you could create an event called “Clicked Unsubscribe Link”, and have a question appear on the following page.

Ramen.Api.page()

Ramen.Api.page()

Notify Ramen that the page has changed. This will trigger a lookup to see if the new page means the current customer should be asked a question.

By default, Ramen will monitor window.location for changes, but you can force this with a call to .page()

Ramen.Api.die()

Ramen.Api.die()

Kill RamenJS. This will:

Credits

Weston Platter did a ton of work getting this site up. Tweet him a cat pic

A Cat Gif

Here is a cat gif:

Catz

Copyright Ramen, Inc. 2012 - 2016