Don’t let recurring donors lapse!

Recurring donors are often your most committed supporters — so it’s especially important not to let them lapse.

ActionKit comes standard with about 300 built-in reports, including a few that can help you identify donors whose cards are about to expire and whose cards recently failed.

These reports are meant to be used for targeting recurring mailings, allowing you to automate the process of checking up on donors.

First, create your mailing

The first step here is to compose a mailing that briefly tells donors their cards are about to expire, how much you appreciate them, and how they can update their credit card so their donations can continue to be processed.

How can they update their credit card? This is where the Update Recurring Donation page type comes in. Either create a page of this type or use the default, and link to it.

This mailing links to the Update your Monthly Donation page

Test it out!

Set up a recurring donation of your own, then send yourself a proof of this mailing using your user ID that has this recurring donation, so you can see exactly what the process will look like to your users.

Sending myself a proof, showing what my mailing will look like, to an email with a recurring donation

Use the built-in targeting

ActionKit’s built-in query “Donors Whose Cards Expire Next Month” is exactly what we need to include on the Target screen. This report finds all subscribers with an active recurring donation whose credit cards are about to expire:

Include the “Donors Whose Cards Expire Next Month” query in your mailing

Make it recurring

Next, on the Proof and Send screen, we’ll need to tell ActionKit we want to make this mailing recurring, which will allow us to set it and forget it.

At the bottom of the proof and send screen is an option to make this mailing recurring:

When we make this mailing recurring, we can set it and forget it

Next, we’ll either choose an existing recurring mailing series or create a new one. For this example, I’ll create a new one:

Creating a new recurring mailing series

In this example, the recurring mailing series only emails once per month. But other recurring mailing series can email much more frequently. Some are even configured to send every hour. If you’re using a recurring mailing series that can potentially send frequently, be sure to configure its targeting to exclude those who already received the mailing recently. Use the People who have recently received a recurring mailing series:

This will exclude anyone who has received recurring series #1 within the last 30 days

You’ll need to look up the recurring series ID in order to know what to put for “Recurring Schedule ID”. WHERE?

Most of the time, you’ll want to exclude all sends of the series you’re working on, but if you want to exclude anyone who has received any recurring series at all, you can use Recurring Schedule ID 0.

Try it out!

The example above shows how to set this up for cards that are about to expire. ActionKit also includes a built-in report for cards that have recently failed. Using this blog post, try to set up a recurring mailing for recently failed cards, too!

Feature Spotlight: Faster mailing builds with summary_user

One of the most common types of support requests we get is about how to make your mailings build faster.

One common root problem of slow mailing builds is often that the underlying reports themselves are slow. Using caching when appropriate can often help, but the biggest wins come from improving the reports themselves.

Maybe you’re using some reports like these in your mailing targeting:

  • When did the user last receive a mailing?
  • When was the user’s last open?
  • When was the user’s last click?
  • When was the user’s last action?
  • When was the user’s last donation?
  • How many actions has this user taken in the last 30 days?

These are common reports, and they’re great questions to ask about your users! They’re great ways of measuring engagement and figuring out who your most committed supporters are.

Unfortunately, these reports can often be pretty slow, too.

And if you’re using slow query reports in your mailings, your mailings are going to take a long time to build their targeting, which means it takes longer to get proofs or get your mailings out the door.

Why it’s slow

The most common reason these reports (and therefore the mailing builds) are slow is these reports are looking through large database tables with millions or hundreds of millions of records. And calculating those results can take a lot of time!

Some of the slowest tables to run reports on include:

  • core_action (all actions ever taken by users)
  • core_open (all mailings ever opened by users)
  • core_usermailing (all mailings ever received by users)

In fact, that’s exactly why we created the summary_user table, which has all of the data you’re commonly looking for in these types of engagement queries, like:

  • When did this user last take action?
  • When did this user last take action from a mailing?
  • When did they last open a mailing?
  • When did they last click a mailing?
  • When were they last subscribed to the default mailing list?
  • When was their last donation?
  • When did we email them last?
  • How many actions have they taken in the last 30 days? 60? 90? 180? 270? 365?

Why this matters

Since we don’t have to look through the entire history of actions and donations and mailings and opens and clicks and so on, every single time, for every single user — because we do all that heavy lifting behind the scenes and keep summary_user regularly up to date, your reports will run SO fast and your mailings will build SO much more quickly.

In my tests, I found that smaller clients will see a speedup of 400X faster mailing builds when using summary_user compared to calculating the same results on other (slow) tables.

For larger clients, the benefits are even greater: we’re talking 3000X faster. So a report that you might have been waiting several minutes or even up to 30 minutes to complete, now completes in seconds when using summary_user.

Here’s how

To get started, you’ll need to edit your query reports to use the summary_user table whenever possible. This will require some custom SQL, but the good news is your queries will be much more straightforward, easier to read and understand, and of course, faster.

Here is an example of some code generated by the point-and-click query builder to calculate the number of actions a user has taken in the last 90 days:

Before: a slow query to calculate actions taken by a user in the last 90 days

If you look closely, you’ll notice that this query joins to the core_action table, which is large and therefore can be pretty slow.

This next bit of SQL code does the exact same thing, but has been rewritten to use the summary_user table. Notice that it’s much more straightforward and easy to read — and of course, it’s much faster too:

After: a fast query using summary_user to show actions taken by a user in the last 90 days

Refer to the database reference on summary_user to get started on transforming your queries.

For best results, start with optimizing a query that is very slow, or a query that is used very frequently in your targeting: go for the biggest, easiest wins first.

But summary_user doesn’t have _________!

Now if you’re thinking “this sounds great, but summary_user doesn’t have this particular stat we really care about” — custom user fields and user updaters are here for you.

These allow you to store whatever information you like about your users in custom user fields (like for instance: how much money did this user give in calendar year 2020?) and keep them up to date with user updaters.

Check out a video version of this blog post, plus our feature spotlight blog post and videos on custom user fields and user updaters for more about how to get started using these powerful features to speed up your mailing builds even more!

Feature Spotlight: Custom User Fields

Custom user fields are a very commonly-used feature in ActionKit. Many clients use them to store information like a user’s employer or occupation, but there are SO many different bits of information that could be useful to store!

In this blog post, we’ll give you a few ideas of things you can do with custom user fields, but what you do with it is completely up to you!

Why should I use custom user fields?

Beyond storing useful data like a user’s employer or occupation, lots of clients like to run reports on historical data, like “how much money did this user given in 2020?” “How much did they give in 2018? 2016?”

Unless someone has a time machine, historical data like that doesn’t change very often. The amount someone gave in 2016 is fixed. But calculating that information from the database — depending on what data you’re retrieving, how far back you’re going, how many users you have, and a few other factors — this can be VERY slow!

Lots of clients also like to us merge queries to calculate suggested ask snippets based on historical donation data including a user’s highest previous contributions, but there are so many ways to calculate suggested asks!

Still, if you’re often using merge queries in your mailings, and you find those merge queries are very slow, you might want to use custom user fields to make your mailings build much more quickly.

Some common reasons your reports, mailing builds, and merge queries might be slow include:

  • Your report / merge query looks at large database tables including millions or hundreds of millions of entries
  • Your report / merge query could benefit from caching or optimization
  • Your report / merge query performs time-consuming calculations on several years of historical data

And when you’re targeting your mailings to hundreds of thousands or millions of people, and doing these calculations each time for every single recipient, that can slow things down even further.

Don’t forget summary_user

For many common situations, we already have fields that you can use — you don’t need to create a custom user field to calculate information like:

  • When did a user last take action?
  • When did a user last take action from a mailing?
  • When did a user last receive a mailing?
  • When did a user last open a mailing?
  • When did a user last click a mailing?
  • When did a user last donate?
  • When was a user last subscribed to the main email list?
  • How many actions did a user take in the last 30 days? 60? 90? 180? 270? 365?

For these questions, see the summary_user table, where we’ve collected these stats and keep them updated.

One way to think about custom user fields is as a supplement to summary_user!

Why this matters

Using custom user fields, your mailing builds will complete MUCH more quickly than if you were doing these queries on the fly.

You can also use custom user fields as snippets available in your pages and your mailings.

Don’t forget — you can target your mailings based on your custom user field data.

Some example ideas

Here are a few example ideas for custom user fields that you could do:

  • Count of donations made in 2020
  • Amount of donations made in 2020
  • Largest one-time donation ever made
  • Amount a user can give before they “max out” (for political parties and candidates)
  • Propensity scores

How to get started

You can of course have your users enter data into custom user fields on forms like surveys and petitions. But to add data in bulk, read on.

First, create a custom user field that will store the information you want to capture. In this example, we’ll use a field called donation_count_2020 to store the number of donations a user made in calendar year 2020.

Next, create a report that calculates the value of what that custom user field should be for each user.

This report calculates the number of donations a user made in calendar year 2020

Notice that the name of the column where we’re calculating the number of donations a user made in 2020 is “user_donation_count_2020” — this is important, as it must match the name of the custom user field we created above, with the “user_” prefix.

The first column here is the user ID, which will be important later when we upload the file.

Then, run your report and view the results. When the results look correct to you, download it as a CSV (comma separated values) file.

Next, create an import page. (As a general rule, when importing custom user fields, I’d make sure the import page was set to not change the subscription status of the users you upload)

Next, upload your file, being sure to check the box that says “Skip Action Creation”. This will make your upload go much faster — though it only works when you’re only uploading custom user fields, which we are here.

When the upload completes, all of the users you imported will have the number of donations they made in 2020 stored in the custom user field donations_count_2020!

Although it may seem strange to upload data from ActionKit back into ActionKit, this is a great way to set up custom user fields — and best of all, take advantage of big speed improvements by not needing to calculate the values every time.

But how do I keep user data up to date?

You’re probably thinking “This is nice, but it’ll never work for us, because I’m not doing a manual import every day to keep this information up to date!”

And you shouldn’t have to! That’s time-consuming, easy to forget or miss, and error-prone. Much better to do it automatically!

This is where user updaters come in. User updaters are a new feature that’s specifically designed to help you keep your custom user fields up to date on a regular schedule. You’ll make a report similar to the one we made above, then set it to run on a schedule. We’ll update your users’ custom fields on a regular basis and you don’t have to think about it ever again!

Give this a try — and be sure and let us know via support how you’re using custom user fields! We love to know all of the creative ways that you’re using ActionKit.

Also be sure to check out a video version of this blog post, plus our feature spotlight blog posts and videos on summary_user and user updaters for more!

Feature Spotlight: User Updaters

First things first: if you haven’t read our feature spotlight on custom user fields, do that before reading this one!

Custom user fields are powerful, but they’re not much use if the data in them is out of date.

For some custom user fields, they don’t need to be updated regularly. Historical data, like the amount of money a user gave in calendar year 2020, isn’t going to change — it’s over and done. You can import that once and be done.

But if you’re tracking information like “how much money has a user given in this current calendar year?”, you’ll want to keep that information regularly up to date.

Sure, you could do a manual import process every day to update that information manually, but it’s easy to forget, or not have time to do it. Better to automate these types of tedious, time-consuming, error-prone processes.

This is exactly why we created user updaters.

User updaters run the custom user field import for you, using the exact same report you made for your initial custom user field import, and we run them on a schedule that you set.

To get started, first create a report for your custom user field import. Or, if you already created one for your initial import, re-use it!

Next, ensure that your report’s column names match the custom user fields, just like we did in the custom user fields feature spotlight.

Also be sure that you’re only including relevant columns in your user updater report. This means one column to identify your user, like user ID or email, and your custom user field columns.

Here’s an example: lots of clients (mainly political parties and candidates) want to know how much money a user can give before they “max out”. Sure, you could calculate that manually and use it in a merge query, but that could make your mailing take a long time to build.

With a user updater, this information stays up to date behind the scenes, and your mailings build lightning fast.

The User Updater Maxout 2021 report, calculating how much money a person can give before they “max out” for this cycle

Notice that we have two columns: one for the user ID and another titled user_maxout_amount_2021. If we haven’t yet created a custom user field with the name maxout_amount_2021, we’ll want to do that before continuing any further.

Next, give your report the updater report category and save.

When your report finishes running, confirm that the results look good to you, spot-checking several users to ensure the results.

Next, create your User Updater. From the Users tab, find User Updaters in the sidebar, then create one. You can run user updaters manually, or on a schedule as you prefer.

This user updater runs on a daily schedule

In the screenshot above, I’ve given my user updater a helpful name and description, and I’ve set myself to receive email updates about whether the updater succeeded or failed on each of its runs.

The Query Report is the actual report that runs (and is imported); you’ll only see reports that have the updater category here, and each query report can only be associated with a single updater.

You can run your updaters on a daily, weekly, or monthly schedule as you prefer, or remove the schedule once you no longer need to update the field. For example, once it’s 2022, I won’t need to update the above field anymore, so I can turn off the schedule.

User Updaters will also tell you the last time they ran, whether it succeeded, which columns it updated, and how many users were updated as part of the run:

Results of the last user updater run: 3 users updated

Keep in mind, user updaters are only used to update custom user fields and user groups!

Check out a video version of this blog post, plus our feature spotlight blog posts and videos on custom user fields and user groups for more great tips!

Feature Spotlight: User Groups

If you’ve read my blog post A Tagging System That Works or seen any of my presentations over the years, you know I love tags! They’re such a powerful feature for categorizing your users, targeting your mailings to them, and building reporting about them.

But over the years, lots of clients have shared feedback about the ways that tags don’t meet all of your needs.

We’ve taken your feedback and created a new system that complements tags, called user groups.

Before we go too deep into what user groups are, let’s talk tags first.

It’s important to remember that you apply tags to pages, not directly to users. Then, when a user takes action on that page, they gain that tag.

One great thing about tags is they’re applied retroactively, meaning if you change a page’s tags, we’ll update the user’s tags automatically as a result.

Where tags fall short

Over the years, you’ve asked us questions like “Can I add a user directly to a tag?” and “Can I remove a user from this tag?”

And while there ARE ways to do these, they’re not straightforward.

You could, for instance, set up an import page, give the import page the tag you wanted, and import a user to add them to a tag. But that’s a lot of work, and probably too much trouble for a single or even a few users.

But removing users from a tag is even more trouble. You’d have to either delete all of the actions that user has taken on pages with that tag, or remove the tag from all of those pages. But then you’re deleting actions, which you probably don’t want to do, or you’re removing those tags from lots of users, which again, you probably don’t want to do.

And this is exactly why we made user groups: so you could add users directly to a group and remove them directly from a group without any side effects.

Like tags, if a user takes action on a page with groups, they will be added to that group. But unlike tags, if you change a page’s group, we DO NOT retroactively go back and update your user’s group memberships.

This isn’t a technical limitation — we could in theory — but since you can remove users from groups manually, we wanted to minimize the chance of automatically adding a user to a group you’ve already removed them from. So we don’t retroactively update group membership when you change a page’s user groups. But for action takers going forward, they will get the new groups.

Another way to understand tags versus groups is to look at the ways a user can gain or lose a tag versus a group:

How a user gains a tag:

  1. Taking action on a page with those tags

How a user is added to a group:

  1. Taking action on a page with those groups
  2. On that user’s Change User overview screen
  3. From an import (using the group or group_id columns)
  4. From a user updater (using the group or group_id columns)
  5. From the REST API

How a user loses a tag:

  1. Deleting this user’s actions on all pages with those tags
  2. Removing those pages’ tags

But these a probably not worth the side effects! I don’t recommend this — instead, groups are probably more appropriate here!

How a user is removed from a group:

  1. On that user’s Change User overview screen
  2. From an import (using the group_remove or group_id_remove columns)
  3. From a user updater (using the group_remove or group_id_remove columns)
  4. From the REST API

Like tags, you can also target your mailings based on user groups, and you can also run reports to analyze performance on user groups.

To get started using user groups, you can either create user groups ahead of time from either the Pages tab > Other > User Groups or from the Users tab > Manage Groups, or you can create them on the fly from the Action Basics screen of your page.

Adding user groups from the Action Basics screen. Groups don’t replace tags – they’re a supplement!

And of course, you can add tags on the user overview screen for any user.

Adding users directly to a group from the user overview screen

Thanks again for providing great feedback on ActionKit — what’s working and not — and telling us all the ways you’re using ActionKit. We’d love to hear about how you’re using groups!

Be sure to check out a video version of this blog post, plus our feature spotlight video and blog post on user updaters for more!

10 More Features Every Client Should Use

At ClientCon 2020, I ran a presentation called “10 More Features Every Client Should Use,” intended to help clients get the most out of ActionKit.

This is the second in the series, continuing from “10 Features Every Client Should Use” I originally ran in 2019.

In both of these presentations, I wanted to highlight a handful of different features that every client would find useful and wanted it to be a good mix — some things quick and easy, others that would take a little more time to set up fully. Here’s a brief overview:

Tag your Pages and Mailings

Tagging your pages and mailings allows you to create robust reporting on the performance of your pages and mailings by category. Tagging is especially useful when using prefixes, like topic-immigration instead of just immigration, as this allows you to group similar tags together.

It’s also never too late to go back and tag old pages and mailings! Not only will your page tags be applied to action takers retroactively, but our advanced search and bulk edit features make tagging old pages and mailings a quick job.

Re-engagement

Setting up a re-engagement process is one of the best ways to boost your open, click, and action rates — as well as your deliverability.

Avoid getting pushed into the spam folder or promotions tab by only sending to your most engaged supporters — and letting the old email addresses go.

New ActBlue Sync

A few long-time ActionKit clients are still using the legacy ActBlue sync, which has a few problems: it erroneously treats recurring donations as multiple one-time donations, refunds don’t show up correctly, and sync failures aren’t recorded.

We built our own ActBlue sync to solve these problems, and almost everyone has happily switched over.

If you’re still using the legacy ActBlue sync, file a support ticket and ask about moving over to the new ActBlue sync!

Always use HTTPS

Web browsers will display warnings in the URL bar for sites that are not using HTTPS. This can cause your visitors to pause and ask themselves “What does it mean that this site isn’t secure? Should I not sign this petition? Does this mean I shouldn’t make a donation?”

We can turn on the “Always use HTTPS” feature for you to prevent these types of warnings, but before we do, you’ll need to make sure all of your images, CSS, Javascript, and any other assets are being loaded using HTTPS, not HTTP.

Once you’ve made these updates in your templatesets, we can flip the switch on our end. Just open up a support ticket and we’ll do the rest!

Review Staff Access

It’s always a good idea to periodically review staff accounts that have access to your ActionKit (or any other system, really) and disable the ones you aren’t using anymore.

The Staff query type in the Query Builder can help you make a quick report of your staff users, who has what access, and when they’ve last logged in.

Just be careful not to disable admin (that’s us!), or any other users that are used by your integrations like ActBlue.

Custom Page Fields

Custom page fields allow you to make big and small changes to your pages without needing a lot of ongoing code changes. This year, we focused on how to add custom Javascript code on a one-off basis.

Timed Sends

Timed sends allow you to deliver mailing to a user in their specific time zone. In other words, if you’ve found that 10:00 am is the best time to send for your users, you can make sure they receive your mailing at 10:00 am — no matter where they live.

Custom User Fields

Custom User Fields allow you to store information about a user like their employer, occupation, membership level, and so much more.

You can also target your mailings based on what’s stored in these custom fields, and we’ve added a new feature to imports that allow you to import data into custom user fields lightning fast.

Cross-site prefill

Cross-site prefill uses a cross-client shared pool of user profiles in order to pre-fill known user data into your form and boost action rates. This is similar to, but different than user recognition based on AKID.

Stop Spam with Recaptcha Challenges

ActionKit has built-in protection against spam bots, but if you find that spammers are still getting through, you can add a Recaptcha challenge to your page.

It’s also possible to configure Recaptcha site-wide and use a custom page field to disable these on a one-off basis for your pages if needed.

To learn more about setting these up, check out the video 10 More Features Every Client Should Use — and file a support ticket if you have any questions or have difficulty setting these up!

How to set up AMP for Email

Ever want to send a survey that you can fill out in an email? Now you can!

AMP for Email (Accelerated Mobile Pages for Email) is a new feature that allows you to do just that. In select email clients (mostly Google, which created AMP, and others who are adopting it), you can add forms and other similar web-like dynamic elements within your emails themselves.

And if your user’s email client doesn’t support AMP? They’ll receive the HTML version of your email instead.

In other words, AMP is NOT meant to replace your current emails. It’s there to supplement them!

Setting up AMP takes a bit of work and has a learning curve, but we’re here to help. Here’s how to get started.

Before you can use ActionKit forms in your AMP emails, you need to add https://mail.google.com as an Allowed Origin under CORS Settings on the Configuration screen. (If you forget to add this as an Allowed Origin, actions will be processed but the form success message won’t display to your users, making it seem like your form did not work.)

You can begin using AMP in your mailings by using any AMP-compatible Email Wrapper. We’ve provided an AMP-compatible Email Wrapper for you (AMP Template with Sidebar), but you can also create your own. Once you’ve chosen a suitable Email Wrapper, the AMP HTML Body field will automatically appear on the Compose screen of your mailing.

It’s important to note that AMP is non-standard HTML. Some elements like img have a direct replacement (amp-img), other elements aren’t supported at all in AMP. There are a large number of features in standard HTML/CSS that are not supported in AMP.

To help you write AMP-compliant email, we have a validator that checks your code for compliance as you go. If the validator finds any tags, attributes, or other code that doesn’t pass Google’s requirements, we’ll issue a warning to help you correct the code. Sometimes the edits you need to make might be in your AMP HTML Body, other times you may need to edit your email wrapper in order to fix the validation error.

To make things even easier, we’ve provided an example form and highlighted some common issues in our documentation.

While you’re testing, you can send yourself AMP-enabled emails if you enable a setting in your email address’s Gmail (or equivalent) account.

In order to send yourself AMP emails, open your Gmail settings. Under General, go to Dynamic Email:

General Settings in Gmail

Make sure Enable dynamic email is checked, then click on Developer settings and enter your sender email to always allow dynamic emails from this sender, like this:

Preview dynamic emails during development

That will work to send yourself test AMP emails, but before you can send AMP emails to your supporters, you’ll need to first register with Google. You’ll need to do this once per sender email address (e.g. the email part of this from line: “Shannon Turner” <info@actionkit.com>). This process involves sending a production-quality (non-test) AMP email to Google, and completing a short Google form.

When we registered with Google, we used the following AMP HTML Body when sending our working, production-quality email:

<form class="ak-form" method="POST" action-xhr="https://clientcon.actionkit.com/act/" accept-charset="utf-8">
    <input type="hidden" name="page" value="what-trainings-would-you-like-next">
    <input type="hidden" name="response_type" value="json">
    <input type="hidden" name="email" value="{{ user.email }}">
    <input type="hidden" name="source" value="mailing">
    <input type="hidden" name="mailing_id" value="{{ mailing_id }}">
    <div class="ak-grid-row">
        <div class="ak-grid-col ak-grid-col-12-of-12">

            <div class="ak-mobile-padding ak-text-expander">
                <p>{{ user.first_name|default:"ActionKitties"|title }},</p>
                <p>We've run a ton of trainings over the years -- some highlights include:</p>
<ul>
<li><a href="https://www.youtube.com/watch?v=S7h__59AJpg">ActionKit 101</a></li>
<li><a href="https://www.youtube.com/watch?v=hedlvovaI6o">Advocacy 101</a></li>
<li><a href="https://www.youtube.com/watch?v=5bm-xcSiGdk">Fundraising 101</a> </li>
<li><a href="https://www.youtube.com/watch?v=hNAT5EdBKxc">Mailing Wrappers &amp; Template Blocks</a></li>
<li><a href="https://www.youtube.com/watch?v=H7brrWwtK7o">Building Dashboards</a></li>
<li><a href="https://www.youtube.com/watch?v=Z3p3KMU-KW0">Intro to the Query Builder</a></li>
<li><a href="https://www.youtube.com/watch?v=Y8eSnR741H8">Intermediate Mailings</a></li>
</ul>
                <p>But we're curious: what topics would you like to see covered in the next training?</p>
                    <p><b>Complete the ActionKit survey in this email below to let us know -- you can submit the survey right from this email!</b></p>
                <hr>
            </div>

        </div>
    </div>

    <div class="ak-grid-row">
        <div class="ak-grid-col ak-grid-col-4-of-12">
            
            
            
            <div id="survey-contact" class="ak-styled-fields ak-labels-overlaid ak-errs-below">
                <ul class="compact" id="ak-errors"></ul>

  


</div>

            </div>
            
            

            
        </div>
        <div id="ak-survey-questions" class="ak-grid-col ak-grid-col-8-of-12">
            <div class="ak-field-box ak-field-box-padded ak-styled-fields ak-labels-above ak-errs-below">

                
                <div>
                    <label class="ak-survey-question-label">
                        <h3>                        What level of complexity would you like to see more trainings on?</h3>
                    </label>
                    <div class="checkbox-item ak-survey-checkbox-set ak-input-set"><label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_complexity" id="id_action_action_training_complexity_1" value="1"> Beginner-friendly, please. These trainings are especially helpful for onboarding new staff.</label><br>  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_complexity" id="id_action_action_training_complexity_2" value="2"> Intermediate. Beginner-level trainings are already recorded and we&#39;re eager to dig deeper.</label><br>  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_complexity" id="id_action_action_training_complexity_3" value="3"> Advanced. The intermediate level trainings aren&#39;t advanced enough for me!</label> </div>
                </div>
                
                <div>
                    <label class="ak-survey-question-label">
                        <h3>                        Broadly, what areas would you like to see more trainings on?</h3>
                    </label>
                    <div class="checkbox-item ak-survey-checkbox-set ak-input-set">
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_pages" value="Pages"> Pages</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_targets" value="Targets"> Targets</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_templatesets" value="Templatesets"> Templatesets</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_custom_page_fields" value="Custom Page Fields"> Custom Page Fields</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_a_b_page_tests" value="A/B Page Tests"> A/B Page Tests</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_delivery" value="Delivery"> Delivery</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_suggested_asks" value="Suggested Asks"> Suggested Asks</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_tags" value="Tags"> Tags</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_spam_prevention" value="Spam Prevention"> Spam Prevention</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_events" value="Events"> Events</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_custom_event_emails" value="Custom Event Emails"> Custom Event Emails</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_mailings" value="Mailings"> Mailings</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_custom_mailing_fields" value="Custom Mailing Fields"> Custom Mailing Fields</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_email_wrappers" value="Email Wrappers"> Email Wrappers</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_custom_email_wrapper_fields" value="Custom Email Wrapper Fields"> Custom Email Wrapper Fields</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_merge_files" value="Merge Files"> Merge Files</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_merge_data" value="Merge Data"> Merge Data</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_intermediate_snippets" value="Intermediate Snippets"> Intermediate Snippets</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_advanced_snippets" value="Advanced Snippets"> Advanced Snippets</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_re-engagement" value="Re-engagement"> Re-engagement</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_pre-flight_mailing_dashboard" value="Pre-flight mailing dashboard"> Pre-flight mailing dashboard</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_reports" value="Reports"> Reports</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_building_dashboards" value="Building dashboards"> Building dashboards</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_query_templates" value="Query templates"> Query templates</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_users" value="Users"> Users</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_custom_user_fields" value="Custom User Fields"> Custom User Fields</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_advanced_features" value="Advanced Features"> Advanced Features</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_salesforce_sync" value="Salesforce sync"> Salesforce sync</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_everyaction_sync" value="Everyaction sync"> Everyaction sync</label><br>
  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_topics" id="id_action_action_training_topics_not_sure" value="Not sure"> Not sure</label><br>
 </div>
                </div>
                
                <div>
                    <label class="ak-survey-question-label">
                        <h3>                        Are there other resources you want to see more of?</h3>
                    </label>
                    <div class="checkbox-item ak-survey-checkbox-set ak-input-set"><label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_other_resources" id="id_action_action_training_other_resources_documentation_-_the_campaigner_s_guide_is_very_helpful" value="Documentation - the campaigner&#39;s guide is very helpful"> Documentation - the campaigner&#39;s guide is very helpful</label><br>  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_other_resources" id="id_action_action_training_other_resources_documentation_-_the_developer_s_guide_is_very_helpful" value="Documentation - the developer&#39;s guide is very helpful"> Documentation - the developer&#39;s guide is very helpful</label><br>  <label class="ak-survey-checkbox-choice"><input type="checkbox" class="ak-survey-input" name="action_action_training_other_resources" id="id_action_action_training_other_resources_blog_posts_tutorials_and_how-to_guides" value="Blog posts, tutorials, and how-to guides"> Blog posts, tutorials, and how-to guides</label><br> </div>

                </div>
                
                <div>
                    <label class="ak-survey-question-label">
                        <h3>                        Specifically, what would you like us to do more trainings on?</h3>
                    </label>
                    <textarea class="ak-survey-input" name="action_action_training_freeform" id="id_action_action_training_freeform" rows="4" style="height:5.0em; width: 80%;" ></textarea>

                </div>
                
                <div>
                    <label class="ak-survey-question-label">
                        <h3>                        Anything else you want to share?</h3>
                    </label>
                    <textarea class="ak-survey-input" name="action_action_training_anythingelse" id="id_action_action_training_anythingelse" rows="4" style="height:5.0em; width: 80%;" ></textarea>
                    <br><br>
                </div>
                

                <button type="submit" class="ak-submit-button" value="Submit Survey" style="border-radius: 16px; background-color: #dd0000; display: inline-block; padding: 0 22px; margin-bottom: 10px; line-height: 200%; height: 32px; color: #fff; font-size: 16px; font-weight: bold; text-transform: uppercase; font-family: Helvetica, Arial, sans-serif; text-align: center; text-decoration: none;">Submit Survey</button>

                <div submit-success>
                  <template type="amp-mustache">
                    Your survey responses have been recorded! Thanks for letting us know what you'd like to see!
                  </template>
                </div>
                <div submit-error>
                  <template type="amp-mustache">
                    Hmm, something went wrong and your survey response didn't go through.
                  </template>
                </div>

            </div>
        </div>

    </div>
</form>

You can modify the above to meet your needs, but hopefully this helps get you started.

While testing, don’t forget that any proofs you get WILL RESULT IN AN ACTION BEING TAKEN IF YOU SUBMIT THE FORM, just like if you were to submit a form after clicking a non-AMP email proof.

If you have trouble setting up your AMP email, consult the AMP for Email specification. If you’re still stuck, file a support ticket!

Looking forward to seeing what you come up with!

More ways to provide suggested ask snippets

In Fundraising in ActionKit? Don’t forget these tips! we showed how you can use suggested ask rules to show personalized donation suggestions.

But that’s not the only way to do this! Lots of clever clients have developed other ways to show personalized suggestions, and those are worth a mention here too.

Many of these tips are explained in detail in our Intermediate Mailings training, which you may find useful!

Some clients like to use the {{ donations.highest_previous }} snippet in their mailings, along with the |multiply filter in order to show different potential giving levels.

Assuming someone has given previously, the {{ donations.highest_previous }} snippet will show the highest one-time donation they’ve given before.

When to use requires_value

To restrict your mailing to ONLY those who have given previously, use the {% requires_value donations.highest_previous %} snippet. If you use this, you’ll also want to adjust your targeting to make sure your mailing only goes to previous one-time donors.

But you don’t have to use the {% requires_value donations.highest_previous %} snippet. In fact, there’s a good argument to be made that even if someone hasn’t given before, you still want to make an ask! Suggested ask rules do a good job of covering this situation, but this post is all about other ways of approaching the same problem. In this case, you’ll want to remove the {% requires_value donations.highest_previous %} snippet from your mailing.

Adding donation levels

Using the |multiply filter, we can show a higher (or lower) amount than the user’s highest previous one-time donation.

For example, {{ donations.highest_previous|multiply:1.5 }} will multiply a user’s highest previous one-time gift by 1.5. If someone’s highest gift before was $10, this snippet will show $15.

You can use as many of these different levels as you like in your mailings, to offer a set of choices. Use the amount={{ donations.highest_previous|multiply:1.5 }} and prefill=1 URL parameters when creating links in your mailings.

Get lots of previews and proofs

Let’s say we have a user whose highest previous one-time gift was $10, and we want to show them a multiple of 1.25 to ask them for $12.50.

Using the {{ donations.highest_previous|multiply:1.25 }} snippet looks wrong though: instead of $12.50, we see $12.5 in the preview.

Getting lots of previews and proofs is so important — it’s the only way you’ll be able to notice these sorts of oddities.

To fix this so you can properly display cents even when the last digit is a zero, use the |floatformat:2 filter. This tells ActionKit “I expect this to be a ‘floating point number’ (also known as a decimal number), so always round it to two digits.”

You’ll want to apply this to all of your donation snippets that use |multiply, even if you don’t notice problems with them. (Depending on the initial values and how you’re multiplying, you might see problems, or you might not).

So you’ll end up with: {{ donations.highest_previous|multiply:1.25|floatformat:2 }} – it’s important that the floatformat comes last (is the rightmost filter), because otherwise it may not do anything.

Re-using variables

Behind the scenes, ActionKit does a database calculation every time you use the {{ donations.highest_previous }} snippet (and some other snippets, too). That’s fine, but if you use that snippet more than a few times in your mailing, you might want to switch to another way of using it, or your mailing send speed might be slower than it needs to be.

Using the {% with %} tag, we can assign the value of {{ donations.highest_previous }} to a variable. In these examples, let’s assign them to the hpc variable.

First, we assign the variable using the tag {% with donations.highest_previous as hpc %} and then at the end of the email, we’ll use {% endwith %} to tell ActionKit we don’t need this anymore.

This also has the added benefit that we don’t need to type {{ donations.highest_previous }} over and over again; we can instead use {{ hpc }} to mean the same thing.

Now we can use our filters on the hpc variable in the same way as before, like {{ hpc|multiply:1.25|floatformat:2 }}.

Rounding to nearest $5 / nearest $10

Using some math tricks, it’s also possible to round to the nearest $5 or nearest $10 if we don’t care about cents.

To round to the nearest $5, use {{ hpc|multiply:0.2|floatformat:0|multiply:5 }}. This uses some math tricks and rounding (notice the floatformat filter is in the center, not at the very end as usual) to get the value we’re looking for.

To round to the nearest $10, use {{ hpc|multiply:0.1|floatformat:0|multiply:10 }}.

It’s also possible to use these alongside other multiplication levels, like an HPC x 1.5, rounded to the nearest $10: {{ hpc|multiply:1.5|multiply:0.1|floatformat:0|multiply:10 }}.

There’s lots more tricks you can use to ask for different donation amounts from your users — whether you’re using suggested ask rules or not, ActionKit has lots of ways to personalize your mailings!

Fundraising in ActionKit? Don’t forget these tips!

There are so many different ways of fundraising with ActionKit. Many clients use ActBlue in combination with ActionKit; others use ActionKit’s donation pages exclusively. Here are some of the most common tips and tricks we recommend when fundraising.

Daisy-chain your pages

People who sign your petitions are on board with your organization. They believe in your mission. Nudge your supporters to take that next step by sending action takers to a donation page!

By default, when a user takes an action on one of your pages, ActionKit will send them to a thank you page, usually with sharing options. But you can configure this instead to send them to a donation page. On the After-action info screen, change the Redirect URL to the URL of one of your donation pages.

By default, ActionKit redirects action takers to a thank you page
Change the Redirect URL to send action takers to the page of your choice, usually a donation page

Set up a Confirmation Email

Donors expect a receipt when they donate, and with ActionKit it’s easy to provide one! On the After-action info screen, set your Confirmation Email to include key details about the donation, like the amount and date. (The snippets menu on the Confirmation Email editor has all of these snippets you’ll need).

This confirmation email has all the details users expect, and you can add more customizations using the snippets menu

When sending a confirmation email to users about their donations, we store an exact copy of that email in case they don’t have it anymore and need it re-sent to them. You can re-send the confirmation email from a user’s Donation History screen:

You can re-send confirmation emails upon request. Note that this feature is only available for certain types of confirmation mailings, and only for donations made after February 2019, when this feature was introduced.

Use Suggested Ask Snippets

ActionKit allows you to automatically configure what amount of money to ask for based on a user’s previous giving history. We provide some suggested ask rules in ActionKit to help you get started, but you can also customize your own.

Once you have suggested ask rules you’re happy with, you can attach them to a donation page. When you do this, the donation page will automatically use these rules to determine how much to ask for from each user.

On the Action Basics screen of your donation page, you can select a suggested ask rule

You can also use these suggested ask rules to personalize your mailing content. When you use a donation page that uses a suggested ask rule as your mailing’s landing page, you can take advantage of the suggested_ask snippet.

Select a donation page with a suggested ask rule as your mailing’s landing page in order to use suggested ask snippets

This inserts the ask amount for each user defined by your suggested ask rules.

You can use the suggested ask snippet with ActionKit or ActBlue donation pages. If you’re linking to an ActionKit donation page, the amount for each user will be pre-selected on the page.

With ActBlue, you can use the suggested ask snippet in a URL in order to pre-fill the donation amount. If you want to override all the suggested amounts shown, you can provide the amounts URL parameter with a comma separated list of numbers, like amounts=7,14,21,28,35,42,49 to have the user be able to choose from $7, $14, $21, $28, $35, $42, or $49 rather than the defaults for that page.

This isn’t the only way to do suggested asks, either! One of the things I like most about ActionKit is how there are often many different ways of approaching the same problem. But give that a try — suggested ask rules can be a great way to boost your donations!

Conditional survey questions

Ever want to make survey questions or user form fields appear conditionally based on user responses, so if a user answers in a specific way other follow-up questions become visible?

Here’s one way you can do just that!

First, you’ll want to make sure you’re using a templateset that supports the Custom JS custom page field. (This is a super common way to customize your templates, so we wrote a short post on how to set this up) This will let you write and run Javascript that you can use on your page.

Next, we’ll create all of the survey questions (or user form fields) that we want to appear on the page. Configure them exactly as you like.

For a reference of everything covered in this blog post, you can view a live demo here: https://demo.actionkit.com/survey/we-need-green-new-deal/

Here’s how I configured the survey questions in this example:

Survey Question 1
Survey Question 1

Survey Question 2
Survey Question 2

Survey Question 3
Survey Question 3

Survey Question 4
Survey Question 4

You can configure your survey questions or user form fields as you like, though you’ll have to make some adjustments to the Javascript code provided below to make sure the field names match.

Save your page and view it to make sure all of the fields look exactly the way you want.

The survey page shows all four questions
The survey page shows all four questions

Once they’re configured, return to the Action basics screen of your page.

Scroll to the bottom and add a Custom JS custom page field.

Custom page field Javascript
Custom page field Javascript

Add this code in the Custom JS custom page field and save:

function hideSecondaryQuestions() {
// This hides the secondary survey question questions and their labels.
// Customize this by changing the selectors to match your fields

$('.ak-survey-input[name="action_gnd_jobs_medicareforall"]').hide()
$('.ak-survey-input[name="action_gnd_jobs_medicareforall"]').prev().hide()

$('.ak-survey-input[name="action_gnd_transit_priority"]').hide()
$('.ak-survey-input[name="action_gnd_transit_priority"]').prev().hide()

$('.ak-survey-input[name="action_gnd_renewables_priority"]').hide()
$('.ak-survey-input[name="action_gnd_renewables_priority"]').prev().hide()
}

function showSecondaryQuestions(primary) {
// This shows the secondary survey questions and their labels.
// Customize this by changing the values to match your primary question's values,
// and the selectors to match your secondary questions
if (primary.val() == 'jobs') {
$('.ak-survey-input[name="action_gnd_jobs_medicareforall"]').show()
$('.ak-survey-input[name="action_gnd_jobs_medicareforall"]').prev().show()
}
else if (primary.val() == 'transit') {
$('.ak-survey-input[name="action_gnd_transit_priority"]').show()
$('.ak-survey-input[name="action_gnd_transit_priority"]').prev().show()
}
else if (primary.val() == 'renewables') {
$('.ak-survey-input[name="action_gnd_renewables_priority"]').show()
$('.ak-survey-input[name="action_gnd_renewables_priority"]').prev().show()
}
}

// Hide secondary questions when the page loads
$(hideSecondaryQuestions())

$('#id_action_gnd_excited').on('change', function() {
// When changing the primary question value:
// hide all secondary questions, then show only the ones relating to your choice
hideSecondaryQuestions()
showSecondaryQuestions($(this))
})

Now, when you visit your page you’ll see that only the first survey question appears when you load the page, and when you answer it, the relevant second question appears.

Now survey questions 2-4 have been hidden until you select an answer for question 1
Now survey questions 2-4 have been hidden until you select an answer for question 1

Of course, you can customize your code to reveal more than one question at a time, and if you were clever with your field names or selectors you could show and hide the relevant fields with fewer steps. You could also customize the hideSecondaryQuestions function to clear any existing secondary answers in case a user switches their primary question’s answer.

But this is a good starting point, and we’d love to see what you come up with!