nyco/wp-send-me-nyc

A developer plugin for WordPress that enables sharing website links via SMS or Email.

Installs: 85

Dependents: 0

Suggesters: 0

Security: 0

Stars: 0

Watchers: 14

Forks: 0

Type:wordpress-muplugin


README

A developer plugin for WordPress that enables sharing website links via SMS or Email. It uses Twilio for the SMS service, Amazon SES for the email service, Bitly for url shortening, Timber for email template rendering, and WordPress Multilingual Plugin for translating email content.

Installation using Composer

$1 This package uses Composer Installers to install the package in the Must Use plugins directory (/wp-content/mu-plugins):

composer require nyco/wp-send-me-nyc

Not using Composer? Download an archive of the code and drop it into the mu-plugins directory.

$2 Create a proxy PHP loader file inside the mu-plugins directory, or use the one included with the plugin:

mv wp-content/mu-plugins/wp-send-me-nyc/autoloader-sample.php wp-content/mu-plugins/send-me-nyc.php

Initialization

The sample autoloader contains the basic code required to initialize the plugin. It will...

Note: The SMNYC\SmsMe and SMNYC\EmailMe classes extend the SMNYC\ContactMe class. Any of the three could be extended further or have their properties modified to accommodate custom settings or services.

Configuration

Each settings section corresponds to a specific service that needs to be configured to work with your WordPress installation. These can be configured in the WordPress admin settings or as PHP constants. If both the WordPress admin setting and the PHP constant setting of the option are set, the WordPress admin setting will be preferred.

Bitly Service Settings for URL Shortening

Admin Setting WordPress Option PHP Constant
Bitly Shortening API Link smnyc_bitly_shortener SMNYC_BITLY_SHORTENER
Bitly Access Token smnyc_bitly_token SMNYC_BITLY_TOKEN

Twilio Service Settings for SMS

Admin Setting WordPress Option PHP Constant
Account SID smnyc_twilio_user SMNYC_TWILIO_USER
Sender Phone Number smnyc_twilio_from SMNYC_TWILIO_FROM
API Key SID smnyc_twilio_api_key_sid SMNYC_TWILIO_API_KEY_SID
API Key Secret smnyc_twilio_api_key_secret SMNYC_TWILIO_API_KEY_SECRET

Amazon SES Settings for Email

Admin Setting WordPress Option PHP Constant
Key smnyc_aws_user SMNYC_AWS_USER
Secret smnyc_aws_secret SMNYC_AWS_SECRET
From Email Address smnyc_aws_from SMNYC_AWS_FROM
Email Display Name (optional) smnyc_aws_display_name SMNYC_AWS_DISPLAY_NAME
Reply-to (optional) smnyc_aws_reply SMNYC_AWS_REPLY

Note: This plugin works nicely with the NYCO WordPress Config plugin.

Custom Post Types

These custom post types are created to store reusable SMS and Email content that is sent in our messages.

SMNYC SMS

An example of post content could include the following;

REMINDER: you may be eligible for these NYC Programs: {{ BITLY_URL }}

The template tag {{ BITLY_URL }} will be replaced with a shortened Bitly url that is intended to be shared with the recipient. The SMNYC SMS post type does not require any specific templating.

For more dynamic content, you can include an input for sharetext and include the template tag {{ SHARE_TEXT }} into the post content.

{{ SHARE_TEXT }} {{ BITLY_URL }}

SMNYC Email

An example of post content could be the same as the SMS, however, you may not need to use the Bitly shortener for the url. In this case, replace {{ BITLY_URL }} with {{ URL }}.

REMINDER: you may be eligible for these NYC Programs: {{ URL }}

The SMNYC Email post type requires a template controller that extends the Timber\Post class and a Twig file containing the template that will render the content into an HTML email. The sample controller contains a working class that extends Timber\Post. Move this file to the root of your active theme directory.

mv wp-content/mu-plugins/nyco-wp-send-me-nyc/controllers/smnyc-email-single-sample.php wp-content/themes/theme/smnyc-email.php

The sample email contains a working email twig template. Use this file or create a file within your Timber Views directory called emails/single.twig. This is where the HTML markup for your email will be placed.

Customization

The path to the controller file and class contents can be used as is or modified as needed. By default, SMNYC\EmailMe requires a file called smnyc-email.php in the root of the activated WordPress theme that contains the the controller class. However, different path can be passed to the SMNYC\EmailMe class on instantiation in the auto loader;

$email = new SMNYC\EmailMe('controllers/smnyc-email.php');

Examining the smnyc-email.php file, we can see that the class has a template constant.

/** The twig template for emails */
const TEMPLATE = 'emails/single.twig';

This is the path inside the views where the email template is stored. Modify the string with a different path if desired. The smnyc-email.php also contains a method called ->addToPost() where programmable post content can be added to pass to the view when it is rendered.

Sending a Message

WordPress Admin Ajax is used to send data from the front-end to the plugin. The createEndpoints() method of the instantiated SMNYC\EmailMe and SMNYC\SmsMe objects will add ajax actions when the plugin is initialized. Actions using wp_ajax_{$_REQUEST[‘action’]} and wp_ajax_nopriv_{$_REQUEST[‘action’]} are registerd. Hidden inputs can be used to configure the data that is sent via the script below.

{# .twig #}

<form action="https://mysite.com/wp-admin/admin-ajax.php" method="post" data-js="smnyc">
  <input type="hidden" readonly name="action" value="sms_send" />
  <input type="hidden" readonly name="url" value="https://mysite.com/my-url-to-share/" />
  <input type="hidden" readonly name="template" value="my-sms-post-template" />
  <input type="hidden" readonly name="lan" value="en" />
  <input type="hidden" readonly name="sharetext" value="{{ message }}" />
  <input type="hidden" readonly name="hash" value="{{ hash }}" />

  <input name="to" placeholder="Phone Number" required="true" type="tel" />
  <button class="btn btn-primary btn-small" type="submit">Share</button>
</form>

The default actions to use the SMS and Email services are listed below.

Description Action
Twilio Service SMS send action sms_send
Amazon SES Service email send action email_send

Values

Name Value Description
to A valid email address (validates against the FILTER_VALIDATE_EMAIL validate filter) or phone number (10 digit number including area code), depending on the action.
action The Ajax action callback name; sms_send or email_send.
url The URL to be shared with the recipient, this is what replaces the contents of the {{ BITLY_URL }} and {{ URL }} in the post content.
template The slug of the SMNYC Post to use as the template for sms or email content.
lang The language code of the template content. This should generally be the same as the current language of the page document. This value is passed to the wpml_object_id filter provided by WPML.
hash Required to prevent CSRF. The plugin ships with a helper function to generate a new hash value to pass to your view. Below is an example of adding a hash to Timber context that is passed to the view template.

SMNYC\hash()

/* php */

// Retrieving a hash using the SMNYC helper function.
$context['hash'] = SMNYC\hash('https://mysite.com/my-to-share/');

Below is an example script that adds a submit event listener to the form, serializes the form data on submit, and passes the data as a JSON object to the Fetch API.

/* JavaScript */

// https://www.npmjs.com/package/form-serialize
import FormSerialize from 'form-serialize';

let FORM = document.querySelector('[data-js="smnyc"]');

FORM.addEventListener('submit', (event) => {
  // To send the data with the application/x-www-form-urlencoded header
  // we need to use URLSearchParams(); instead of FormData(); which uses
  // multipart/form-data
  let formData = new URLSearchParams();

  // Serialize the form data.
  let data = FormSerialize(FORM, {hash: true});

  // Iterate over our serialized data and append to formData.
  Object.keys(data).map(k => {
    formData.append(k, data[k]);
  });

  // Send the request via the Fetch API.
  fetch(FORM.getAttribute('action'), {
    method: FORM.getAttribute('method'),
    body: formData
  }).then(response => response.json())
    .then(response => {
      // My Response handler
    }).catch(data => {
      // My Error handler
    });
});

Response Codes

Below are various response codes returned by the Email/SMS service and their meaning.

Codes Meaning
General
9 The hash provided is invalid. See the values table for a description of the SMNYC\hash() usage.
-1 The configuration is invalid.
400 A URL is missing from the request. See the values table for a full list of required values.
Email
1 Missing email address. See the values table for a full list of required values.
2 Invalid email address.
3 An exception from the Amazon SES service. Reference the PHP SDK docs for error descriptions.
SMS Errors
1 Missing phone number. See the values table for a full list of required values.
2 Invalid phone number. Must be a 10-digit number including area code. The final value should be without spaces, dashed, etc.
Twilio Response
30006 Unable to send to number provided.
21611 The outbox queue is full (please try again later).
30007 Invalid message body.
30009 Ephemeral errors that a retry might solve.
... Reference the Twilio Docs for other errors.

Actions

smnyc_message_sent

This action is fired after a message is sent successfully.

...args

  • String $type Email/SMS/whatever the class type is.
  • String $to Recipient of message.
  • String $guid Session GUID.
  • String $url URL to that has been shared.
  • String $msg The body of the message.

Examples

add_action('smnyc_message_sent', function($type, $to, $uid, $url, $message) {
  // Successful message sent handler
}, 10, 5);

The Mayor's Office for Economic Opportunity

The Mayor's Office for Economic Opportunity (NYC Opportunity) is committed to sharing open source software that we use in our products. Feel free to ask questions and share feedback. Interested in contributing? See our open positions on buildwithnyc.github.io. Follow our team on Github (if you are part of the @cityofnewyork organization) or browse our work on Github.