In the Lab: How to build a Custom Block for the GiveWP Totals Shortcode

Welcome back to the Lab!

This tutorial will cover how you can use the classic Give Totals shortcode, from the very popular donations plugin Give, and turn it into a completely custom designed block for the new WordPress block editor. Emphasis on custom design. The classic shortcode was fairly plug-and-play, but converting it into a block gives you full control over design and reusability. ✨

Sound good? Let’s do this!

Let’s have a look at what we’ll be building:

Now for comparison’s sake, this is what just dropping the Give Totals shortcode into the editor gives us:

Shortcode = great.

Custom block = Super Great!

On top of looking super great, there are a few user experience upsides over just using the shortcode. They include:

  • You don’t have to know the Form IDs (depending on the approach you take)
  • You don’t have to use the Give WP Shortcode Builder
  • You get an actual preview in the Editor. With the shortcode, you don’t.

Our setup for this tutorial:

  • Developing on our Local Machine
  • Give Donation Plugin installed and active
  • A couple of Give Donation forms set up
  • Block Lab installed and active

The general process for building a block goes like this:

  1. Set up and configure the block in the WordPress admin using Block Lab
  2. Build the block template using some simple PHP and HTML

Step 1: Set up and Configure the Block

In the WordPress Admin, got to Block Lab > New Block

You should see something like this:

This screen is the block builder. Here we are going to:

  1. Give our block a name
  2. Add the fields that we want our block to include (think of it like a form)
  3. Configure a few block properties (Icon, category, etc)

So our block is going to be called Give Totals. Yours can be whatever you want.

Now for our fields, the best approach here is to refer to whatever design you’re working with. Our design (the yellow-ish one further up), gives us a good idea of the text, images, and settings that we’ll need. One other thing to know about adding fields is that for each field you can:

  • Select the field type. E.g. text, number, image, rich text, etc.
  • Decide where in the Block Editor you want the field to sit. Options are the editor (center content area) and the inspector (side section).

Rule of thumb for where you choose to put each field: content fields go in the editor and fields related to settings / configurations live in the inspector.

So, looking at our design, these are the fields we’re going to roll with:

LabelName (slug)Field TypeLocation
Total Goaltotal-goalNumberEditor
Message messageTextareaEditor
Form 1form-1PostEditor
Form 2form-2PostEditor
Form 3form-3PostEditor
Button Textbutton-textTextEditor
Button URLbutton-urlURLEditor

Heads up
Now let’s pause here for a second. There is a fork in the road here with the approach you can take. The Post field type is a Block Lab Pro field. It’s helpful here as it lets you select from a dropdown the Give Donation Forms you want to interact with. However, if you don’t want to use Block Lab Pro, you can still build this block but you will have to use a number field where a form ID can be added. This will work just as well, but the user will need to know the IDs of the forms they want to interact with.

In the Block Builder, it looks like this:

So a few things to take note of here:

  • We have 3 x Form fields. If you know exactly how many forms you’re going to work with, you can do it like this. If you don’t and would prefer flexible options, the repeater field (coming very soon) of Block Lab Pro would work well here.
  • We configured the block properties over on the right
  • There is a Next Steps prompt at the top that tells us what to do next
  • The Post field types are each set to select from the Post Type Donation Forms (see below)

So with all our fields done, some simple configuration, and hitting Publish, our Custom Block is actually registered and made available to the Block Editor. We can jump into the templating.

Looking at that prompt at the top of the screenshot, you can see it’s telling us we need to create a PHP template file, give it a specific name, and save it to a specific location in our theme.

Pro Tip
You can change the location of your block template files, including having them in a custom plugin, by following these docs.

Step 2: Build the block templates

We now open up our text editor / IDE of choice. I like VSCode, but there are a bunch out there that are great. In our theme folder (note we’ve created a child theme) we want to add a folder called blocks and in it add our PHP template file block-give-totals.php. We’re also going to add a CSS template file called block-give-totals.css in this same folder. As long as the PHP and CSS file names match, Block Lab auto-magically pairs them together.

The file paths for these two new files look like:


So we now have our 2 template files. Let’s code ‘em up.

For our PHP file, it’s going to include some really simple HTML and PHP. The magic happens with a couple of functions that come out of the box with Block Lab. They are block_field() and block_value(). In a nutshell, they let us interact with the fields of our custom block and retrieve / render the data stored when the block is added to a post or page.

For our template file this is what we have:

// Give Totals Block Variables.
$form_1     = block_value( 'form-1' );
$form_2     = block_value( 'form-2' );
$form_3     = block_value( 'form-3' );
$total_goal = block_value( 'total-goal' );
$message    = '';
if ( ! empty( block_value ( 'message' ) ) ) {
    $message = 'message="' . block_value( 'message' ) . '"';
<div class="block-give-totals alignwide">
    <div class="block-give-totals--content">
        <h2><?php echo esc_html( block_value( 'title' ) ); ?></h2>
        $shortcode = sprintf(
            '[give_totals ids="%1$s, %2$s, %3$s" total_goal="%4$s" %5$s]',
        echo do_shortcode( $shortcode );
        <a class="block-lab-totals--button" href="<?php echo esc_url( block_value( 'button-url' ) ); ?>"><?php echo esc_html( block_value( 'button-text' ) ); ?></a>
        <div class="block-give-totals--img-wrapper">
            <img class="block-give-totals--img" src="<?php echo esc_html( block_value( 'image' ) ); ?>">
            <span class="block-give-totals--img-border"></span>

Things to take note of:

  • We’re storing the post objects, the campaign goal, and the message in variables
  • We’re actually working with the Give Totals shortcode
  • We’re using the PHP function sprintf() to insert our variables into the appropriate places in the shortcode
  • We have a button that works with our button-text and button-url fields.
  • We have a bunch of CSS classes spread around
  • We’re sanitising our outputs (i.e. esc_html). If you’re not familiar with this, it’s part of adhering to WordPress coding standards.

That’s our PHP template done. If you’re familiar with the basics of HTML and PHP you can see how super simple that really is.

Now let’s write some CSS to do something with those CSS classes.

Our CSS template file (block-give-totals.css) looks like this:

.block-give-totals {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-gap: 40px;

    display: flex;
    flex-direction: column;
    align-items: flex-start;
    justify-content: center;

.block-give-totals h2 {
    font-size: 40px;
    font-weight: 900;

.block-give-totals .raised {
    font-size: 16px;
    font-weight: 700;
    letter-spacing: 1px;
    text-transform: uppercase;
    color: #FCDC48;

.block-give-totals .give-totals-shortcode-wrap {
    font-size: 16px;
    font-weight: 700;
    color: #555;

.block-give-totals--img-wrapper {
    position: relative;
    padding: 20px;

.block-give-totals--img {
    border: 20px solid #fff;
    z-index: 10;
    position: relative;

.block-give-totals--img-border {
    position: absolute;
    width: 60%;
    height: 100%;
    top: 0;
    right: 0;
    background: linear-gradient(90deg, #FCDC48 0%, #FCA748 100%);
    display: block;

.block-lab-totals--button {
    background: linear-gradient(90deg, #FCDC48 0%, #FCA748 100%);
    display: inline-block;
    color: #555;
    text-align: center;
    padding: 20px 42px;
    margin-top: 40px;
    font-size: 14px;
    text-transform: uppercase;
    letter-spacing: 1px;
    font-weight: 700;
    box-shadow: 5px 5px 10px 0 rgba(0,0,0,0.2);

.give-progress-bar>span {
    background: linear-gradient(90deg, #FCDC48 0%, #FCA748 100%);
    border-radius: 0;

Alrighty. The CSS here does basically the following:

  • Handles layout using a combination of Grid Flexbox
  • Does a bunch of font style adjustments
  • Gives us some image effects. I.e. yellow border thingy and gradient progress bar
  • Make the button look good

To be honest, your theme should cover the majority of the styling here related to text and the button. We’ve included it all here though so you can see more clearly how we end up with our end design.

Now… we’re done!

That’s it. We just…

  1. Built the block in the WP Admin
  2. Added a couple of template files with some simple PHP, HTML, and CSS


Let’s try it out!

Create a new page and add a new block:

When we add the block it activates the block form. In here we can type, upload, and select our content:

Clicking away from the block form it gives us a preview:


And over on the frontend it looks like this:

There we go. Our own custom, nicely designed, block for Give Totals! 

A couple of things you could do to take this further include:

  • Write your CSS to handle smaller screen sizes.
  • Use the repeater field (in Block Lab Pro) to have the block handle variable numbers of forms

Any questions? Ideas? Improvements? Add them in the comments below.

And thanks to Matt Cromwell and the team at Give for working with us on this tutorial.

New Kid on the Block?

Subscribe, stay connected, and keep up to date with the latest.

  • This field is for validation purposes and should be left unchanged.


    1. Thanks for all your help with this one Matt. Give is an amazing plugin and this tutorial was a lot of fun to work on.

Leave a Reply

Your email address will not be published. Required fields are marked *