GithubHelp home page GithubHelp logo

sparkartgroup / blocks-subscribe-email Goto Github PK

View Code? Open in Web Editor NEW
3.0 2.0 1.0 170 KB

Subscribes an email address to a list. Supports a selection of email marketing services.

JavaScript 97.62% Handlebars 0.32% HTML 0.74% CSS 1.32%

blocks-subscribe-email's Introduction

Subscribe Email is a standalone UMD JavaScript module for rendering a mailing list sign up form quickly on a webpage.

It allows developers to quickly include an email collection form on a page without being concerned with the implementation details of a specific mailing list platform. It currently supports mailing lists on SendGrid, MailChimp and Universe.

Getting the Module

You can get the module in any one of the following ways;

  • Download the latest release from GitHub
  • Or install with npm; npm install blocks-subscribe-email
  • Or install with Bower; bower install blocks-subscribe-email

Example Usage

To get started, you'll need to include the script on your page, create a placeholder element, and initialize the module. After you include subscribe-email.js in your project, here's some minimal code you can use to get started quickly;

<div id="subscribe-form"></div>
<script>
window.onload = function() {
  var mySubscribeForm = new SubscribeEmail({
    element: '#subscribe-form',
    service: 'universe',
    key: 'your-api-key-here'
  });
};
</script>

At a minimum, you'll need to change the service and key parameters to match your needs. (Note: MailChimp uses url instead of key).

Advanced Usage

Options

The module can be configured with several optional parameters passed to it's constructor. Here is the full list of options:

element

(Required) A DOM element, jQuery element, or selector string to refer to the placeholder element.

alerter

SubscribeEmail uses blocks-alerter to display response messages from the different mailing list platforms. By default, alerts will be prepended to element and use Alerter's default template. You can turn alerts off by setting alerter: false. If you would like to override the defaults, you can pass in an options hash with options for Alerter. Example;

var mySubscribeForm = new SubscribeEmail({
  element: '#subscribe-form',
  service: 'universe',
  key: 'your-api-key-here',
  alerter: {
    prependTo: 'body',
    template: myCustomTemplate
  }
});

service

(Required) The mailing list platform you are using. Available options are mailchimp, sendgrid and universe.

key

(Required) A string of the API key for your mailing list platform. (This is not required for MailChimp. Instead, you'll have to use url).

url

(Required for MailChimp) A string of the <form action=""> attribute generated by MailChimp which contains MailChimp authentication information. You can get this from MailChimp under "Signup forms > Embedded form code > Naked" and copying just the value from the <form action=""> attribute. It should follow this format: http://{username}.{data center}.list-manage.com/subscribe/post?u={user id}&id={list id}.

submitText

A string to be used on the form's submit button (defaults to "Subscribe").

template

If you want to customize the markup, you can override the default markup by passing in a compiled handlebars template using this option. See the default template for a starting point to work from. A custom template will not work without a form tag that contains id="{{id}}" data-subscribe-instance="{{instanceId}}" and an email input that contains name="{{emailName}}". (Defaults to false).

namespace

Out of the box, the module will generate BEM markup with the namespace subscribe-email, but you can use this option to override the default without passing in a custom template.

Events

You can easily integrate the messages into other parts of your page by listening for events being emitted from the SubscribeEmail instance;

mySubscribeForm.on('subscriptionMessage', function(payload){
  console.log(payload);
});

You can listen for the following events;

subscriptionMessage

Fires whenever the mailing list provider returns a response (both success and failure). The message will be passed to this event as a string.

subscriptionError

This event will fire if the mailing list provider returns an error. Specific details about the error will be passed to the event as a payload object. Note: the payload object may vary depending on the service.

subscriptionSuccess

This event will fire if the mailing list provider returns a confirmation that the email address has been added to the list. Specific details will be passed to the event as a payload object. Note: the payload object may vary depending on the service.

blocks-subscribe-email's People

Contributors

localjo avatar

Stargazers

Erin Keeffe avatar  avatar Pantelis Koukousoulas avatar

Watchers

Joannic Laborde avatar James Cloos avatar

Forkers

joanniclaborde

blocks-subscribe-email's Issues

SendGrid requests fail due to key encoding

SendGrid tokens sometimes contain reserved characters, which they encode when providing you with Subscription Widget embed code, i.e.

<div class="sendgrid-subscription-widget" data-token="kqGHBI%2BxxLFRl%2BaKUyDO965JuAbzHM%2FGvSDJLuM1Iob5FjXAR6ijFp8E1%2FV5hZ%2FsgW%2FUptn9DitMQSny8GniWA%3D%3D"></div><script>!function(d,s,id){var js,fjs=d.getElementsByTagName(s)[0],p=/^http:/.test(d.location)?"http":"https";if(!d.getElementById(id)){js=d.createElement(s);js.id=id;js.src=p+"://s3.amazonaws.com/subscription-cdn/0.2/widget.min.js";fjs.parentNode.insertBefore(js,fjs);}}(document, "script", "sendgrid-subscription-widget-js");</script>

Using kqGHBI%2BxxLFRl%2BaKUyDO965JuAbzHM%2FGvSDJLuM1Iob5FjXAR6ijFp8E1%2FV5hZ%2FsgW%2FUptn9DitMQSny8GniWA%3D%3D as-is doesn't work, resulting in this response:

{"success":false,"message":"Your request cannot be processed."}

If I decode the key and submit that, it works.

No event for on ready

There are some situations where other code needs to know when the subscribe-email module is ready (ie, in order to attach additional event listeners to elements within subscribe-email). Currently subscribe-email doesn't fire any events indicating that it is ready. I vaguely remember discussing this issue before with @pushred but I can't remember if we found a solution to it, or if it just dropped off of our radar?

I propose adding a ready event to subscribe-email that fires once the element is ready on the page.

Missing element shouldn't be fatal

If SubscribeEmail is instantiated on a page without the specified element it currently blows up like this:

Uncaught TypeError: Cannot read property 'id' of null
scripts.js:2283 _setDefaults
scripts.js:2200 SubscribeEmail
scripts.js:393 module.exports
scripts.js:486 (anonymous function)
scripts.js:25725 jQuery.Callbacks.fire
scripts.js:25837 jQuery.Callbacks.self.fireWith
scripts.js:26043 jQuery.extend.ready
scripts.js:26059 completed

//get/set the ID of the HTML element (may be different than the value of element)
options.id = instance.theForm.id || ('subscribe-email-' + options.service);

This error isn't horrible, but it could handle things a bit better for what's probably going to be a fairly common scenario. I think it should throw and log a more direct, helpful error.

Missing required parameter allows errors on contact submit

ActionController::ParameterMissing: param is missing or the value is empty: contact
https://app.getsentry.com/sparkart-fanclubs/sparkart-services/group/34467348/

https://github.com/SparkartGroupInc/sparkart-services/blob/master/doc/api/contacts.md

contact is a required parameter so something must be up there. James also confirmed no error message is returned when he submitted a blank email so guessing it's related since we're not sending back the validation issue response unless it passes the required parameters check there.

Switch to browserstack-runner

Right now, it's hard to keep the browsers array in test/selenium-driver.js up to date with the previous versions of our targeted browsers. Switching to browserstack-runner is a potential solution, since it provides [browser]_previous as a way of selecting the previous version of a browser automatically.

There are two downsides that I'm aware of in switching;

First, I don't think browserstack-runner will run the Selenium webdriver tests, but those tests can probably be replaced with some Mocha tests and run programmatically instead of simulating user action. So, the blocker in that aspect is writing some new tests that cover the same things that the Selenium tests cover.

Second, I was running into some issues with browserstack-runner timing out when running tests on certain browsers. We'll need to find a solution in order to run our tests in all of our target browsers. There's an open issue here: browserstack/browserstack-runner#94

Submissions should be blocked while a request is in process

Currently it's possible to send multiple requests to a service by submitting the subscription form once or more while a previous request is still underway. This is usually handled on the backend with validations and brute force precautions, but can sometimes this can impact the user such as with MailChimp, which enforces a rate limit.

Slow internet connections, intermittent backend delays and errors, user confusion (double-clicking), and other reasons can lead to multiple submissions. Providing indeterminate progress feedback could help, but to be safe, subscribe-email should block submissions while a request is underway to avoid any unexpected behavior.

Can’t require module with Browserify

To test this I’ve been trying to require it into a project using Browserify. Since it’s a UMD module this should work, but currently nothing is happening if I require it as-is. No markup, no errors, no XHR.

Here’s my code:

var Subscribe = require('subscribe-email');

document.addEventListener('DOMContentLoaded', function(){

  new Subscribe({
    element: '#subscribe',
    service: 'universe',
    key: '2366edcf-805b-43bf-b043-9c2f527967d9'
  });

});

I’ve installed the module as a folder at e8b4c40. But when I load my page, nothing’s happening. I confirmed that the DOMContentLoaded event is firing, but I’m not seeing my #subscribe markup populated with anything or any network activity.

Taking a peek at the module I saw that it was pointing to src, which should be fine. But I don’t think this will work under normal conditions because it’s dependent upon hbsfy being present where I’m requiring the module. That’s not a huge ask, I love hbsfy. But this isn’t a standalone UMD module then. So I tried pointing the module’s main to the built version, and I’m getting major resolve errors when I try to compile my project:

[Error: Cannot find module './templates/BEM-with-messaging.hbs' from '/project/node_modules/subscribe-email/build']
[Error: Cannot find module './handlebars/base' from '/project/node_modules/subscribe-email/build']
[Error: Cannot find module './handlebars/safe-string' from '/project/node_modules/subscribe-email/build']
[Error: Cannot find module './handlebars/exception' from '/project/node_modules/subscribe-email/build']
[Error: Cannot find module './handlebars/utils' from '/project/node_modules/subscribe-email/build']
[Error: Cannot find module './handlebars/runtime' from '/project/node_modules/subscribe-email/build']
[Error: Cannot find module './utils' from '/project/node_modules/subscribe-email/build']
[Error: Cannot find module './exception' from '/project/node_modules/subscribe-email/build']
[Error: Cannot find module './utils' from '/project/node_modules/subscribe-email/build']
[Error: Cannot find module './exception' from '/project/node_modules/subscribe-email/build']
[Error: Cannot find module './base' from '/project/node_modules/subscribe-email/build']
[Error: Cannot find module './base' from '/project/node_modules/subscribe-email/build']
[Error: Cannot find module './safe-string' from '/project/node_modules/subscribe-email/build']
[Error: Cannot find module './dist/cjs/handlebars.runtime' from '/project/node_modules/subscribe-email/build']

This is maybe reflective of what happens without hbsfy in the mix. So I suspected that hbsfy might not work properly in a standalone Browserify build. So to learn more about how things are being put together, I created a simple reduction that simply exports an object with a template function generated by hbsfy. To contrast, I also implemented another version that pre-compiles the templates with the Handlebars binary, and requires the runtime. This however turned out to produce a file surprisingly identical to hbsfy’s output, unless I’m missing something. I’ve even added a h1 sanity check on the pre-compiled version to make sure I’m testing the right one.

I’ve pushed up the results of this here: https://github.com/blocks/template

When I run the hbsfy version in the browser (with Beefy) I get:

Error: Cannot find module './template.hbs' from '/template'
    at /usr/local/lib/node_modules/browserify/node_modules/resolve/lib/async.js:42:25
    at load (/usr/local/lib/node_modules/browserify/node_modules/resolve/lib/async.js:60:43)
    at /usr/local/lib/node_modules/browserify/node_modules/resolve/lib/async.js:66:22
    at /usr/local/lib/node_modules/browserify/node_modules/resolve/lib/async.js:21:47
    at Object.oncomplete (fs.js:107:15)

I would say this means my bundle isn’t being transformed with hbsfy, but it is. I see both my precompiled template and the Handlebars runtime in the bundle output. Running the manually pre-compiled version, I get:

Error: Cannot find module './runtime.js' from '/template'
    at /usr/local/lib/node_modules/browserify/node_modules/resolve/lib/async.js:42:25
    at load (/usr/local/lib/node_modules/browserify/node_modules/resolve/lib/async.js:60:43)
    at /usr/local/lib/node_modules/browserify/node_modules/resolve/lib/async.js:66:22
    at /usr/local/lib/node_modules/browserify/node_modules/resolve/lib/async.js:21:47
    at Object.oncomplete (fs.js:107:15)

Resolution problems all around. Digging into this a bit, I took a look at the Handlebars precompiler and among it’s options tried the CommonJS output and requiring a runtime on my own. I found an alias provided just for Browserify, which I’m now using. hbsfy previously did this shim of sorts: https://github.com/epeli/node-handlebars-runtime, which I also tried.

Turns out, Handlebars is weird. I don’t fully understand that discussion, but I think it’s related to our problems here. I have had success in running the template function from the bundle’s source if I move my code outside of modules.exports or some combination like that. I just can’t export it and can’t recreate that working combo at the moment either.

Browserify’s bundling is explained in it’s excellent handbook and looking at the output I think this is working properly. But I’ve no idea why we’re getting all these errors.

One approach I’ve thought of but haven’t tried is using browserify-shim to access the Handlebars.templates global that they still seem to insist on using (Handlebars 2 is out!). But I feel like I shouldn’t have to do that.

Source export vs. UMD

@josiahsprague One other thing we should look into here is the UMD wrapper in the source index. I was really expecting to find just a simple module.exports in there, with Browserify’s own standalone option used to generate the version in build. I know we discussed that but can’t recall whether there was some issue with that approach. Perhaps it’s partly to blame for the hbsfy approach above not working though?

Another option I found: https://github.com/phated/gulp-wrap-umd

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.