Skip to content

Shortcodes and Block Attributes ​

Every shortcode Logo Carousel registers, the PHP template function, and the attribute shape behind each block, for theme work, migrations and generating blocks in code.

This page has two audiences. If you're placing logos in a PHP template, a widget area or a page builder, you want Shortcodes and PHP function. If you're generating blocks in code (a migration script, an importer, a starter-content routine), skip to Block attributes.

Shortcodes ​

A shortcode is a tag in square brackets that WordPress swaps for real output when the page loads. Logo Carousel has two families: one for classic views, and one for Saved Templates built with blocks.

[logocarousel]: a classic view ​

Renders a view built under Logo Carousel → Manage Views (the Classic version). A view is a saved set of display options for the classic logo list.

[logocarousel id="123"]
AttributeRequiredNotes
idyesThe view's post ID (post type sp_lc_shortcodes). Copy it from the Shortcode column on the Manage Views screen.

[logo_carousel_pro id="123"] is an alias that does exactly the same thing. Older content may use it, and it keeps working.

The shortcode prints nothing when id is missing, points at something that isn't a view, or points at a view in the trash. A deleted view therefore leaves no broken markup behind.

A red license notice instead of logos?

When the license isn't active, the shortcode shows an "activate the license" notice in place of the logos, and only to administrators. Everyone else sees nothing, which is why it's often reported as "the logos vanished for visitors." Sites first installed on version 3.3.15 or earlier are exempt. See Installation → Activate your license.

[lc_template]: a Saved Template ​

Renders a Saved Template: a layout built with the blocks and saved once so you can reuse it anywhere, including places blocks can't go.

[lc_template id="456"]
AttributeRequiredNotes
idyesThe template's post ID (post type sp_lc_template). The Saved Templates screen shows the ready-made shortcode for each template.

It prints nothing when:

  • the template doesn't exist or isn't a Saved Template,
  • the Saved Templates module is switched off on Logo Carousel → Getting Started → Modules, or
  • the template isn't published and the visitor can't edit it. Drafts only render for people who can edit them, so you can preview while you work.

A template that contains its own shortcode is ignored rather than looping forever.

This is the shortcode to use for block-built layouts inside a theme template, a widget or a builder without block support.

Page-builder shortcodes ​

Two more shortcodes exist for page-builder integrations: [vc_sp_logo_carousel] (WPBakery, attribute template_id) and [et_pb_sp_logo_carousel] (the Divi 4 module). The builders insert these for you when you add their element. Both point at Saved Templates, so if you're writing a shortcode by hand, use [lc_template] instead. See Integrations.

PHP function: logocarousel() ​

For theme files there's a small helper that prints a classic view:

php
<?php
if ( function_exists( 'logocarousel' ) ) {
	logocarousel( 123 ); // The view's ID.
}
?>

It echoes [logocarousel id="123"], so the same rules apply. The function_exists() check keeps your theme from crashing if the plugin is ever deactivated.

There's no matching helper for Saved Templates. Use do_shortcode():

php
<?php echo do_shortcode( '[lc_template id="456"]' ); ?>

Block attributes ​

Each block stores its whole configuration as block attributes: the JSON inside the HTML comment that opens the block in the post content. Switch the block editor to Code editor (the ⋮ menu, or Ctrl+Shift+Alt+M / ⌥⇧⌘M) to see it.

Block names ​

BlockName
Carouselsp-logo-carousel/carousel
Gridsp-logo-carousel/grid
List Prosp-logo-carousel/list
Marquee Prosp-logo-carousel/marquee
Table Prosp-logo-carousel/table

All five are dynamic blocks: the post stores only the comment with its attributes, and the HTML is built on the server every time the page loads. That's why changing a setting never triggers "This block contains unexpected or invalid content."

The older Classic Shortcode block (sp-logo-carousel-pro/shortcode) simply wraps a [logocarousel] view. Its attributes are shortcode (the view ID) plus a few editor flags.

How the schema works ​

The attribute schema lives in PHP only, under src/Blocks/Schema/ in the plugin. The block.json files have no attributes key; the editor receives the schema from the server when it loads. Two practical consequences:

Grouped attributes ​

Settings are grouped: each inspector panel has one object, and its options live inside it. You'll find navigation.presetIcon, never a flat navPresetIcon.

Shared by all five blocks

AttributeTypeHolds
uniqueIdstringPer-block ID that scopes the block's CSS. Must be unique on the page.
logoSourceobjectmode, patternId and items: the logos themselves (see below)
imagesSettingsobjectLogo Images settings: aspectRatio, resolution, lazyLoad, randomOrder, clickAction, allowSvgUploads, custom width and height
logoImagesStyleobjectLogo Images style: hoverAnimation, margin, and normal / hover states (custom colour, image filter, opacity, overlay)
displayElementsobjectDisplay Elements: which of title, description and Read More show, their order, and styling
tooltipsobjectTooltips
ajaxFilterobjectAjax Live Filter styling
ajaxSearchobjectAjax Search styling
schedulingobjectScheduling: enabled, startDate, endDate
motionEffectsobjectMotion Effects: entrance, scroll, sticky
sectionobjectBlock background, padding and margin
visibilityobjecthideOnDesktop, hideOnTablet, hideOnMobilePortrait, hideOnMobileLandscape
advancedobjectcssClass, cssId
patternDemobooleanTrue while the block still shows demo logos from a pattern or the AI builder
isPreviewbooleanUsed only for the inserter's preview image

Per block

AttributeBlocksHolds
layoutallLayouts. Its shape differs per block (see below)
navigationCarouselNavigation Arrows
paginationCarouselPagination Dots
gridPaginationGrid, List, TablePagination: paginationType (loadMore or number), logoShowPerClick, alignment, plus loadMore and number styling
marqueeDisplayElementsMarqueeSeparate Display Elements settings for the standard and ribbon styles
tableTitlesTableThe header row: enabled, the three column labels, alignment, height and styling

The layout object ​

layout holds a style key, a shared object for settings every style uses, and one object per style for settings each style remembers on its own. That's why switching a Carousel from Standard to Center and back restores your Standard columns.

BlockStyle key and valuesPer-style objects
CarouselcarouselStyle: standard, center, staggered-carousel, multirowstandard, center, staggered, multirow
GridgridStyle: standard, strip, staggered, zigzagstandard, strip, staggered, zigzag
ListlistStyle: left, center, rightleft, center, right
MarqueemarqueeStyle: standard, wave, ribbonstandard, wave, ribbon
Table(one style)style holds the table lines and background

Where a setting lives varies by block. On a Carousel, columns is per style (layout.standard.columns) while autoplay is shared (layout.shared.autoplay). On a Grid, columns sits in layout.shared. When in doubt, read what the editor saved.

Responsive values use one shape everywhere: a device map, plus a unit map when the value has units.

json
"gapBetweenLogos": {
	"device": { "Desktop": 15, "Tablet": 15, "Mobile": 15 },
	"unit": { "Desktop": "px", "Tablet": "px", "Mobile": "px" }
}

Logos live in logoSource.items ​

Block logos are stored in the block, not in a post type. Each block has its own list in logoSource.items, and the images themselves are ordinary Media Library attachments. (The classic version's logo post type is separate; blocks don't read it.)

Each item looks like this:

KeyNotes
idAny string unique within the block
mediaIdThe attachment ID. This is the main source of the image.
imageUrlFallback image URL, used when there's no mediaId
titleUp to 120 characters. Shown by Display Elements and tooltips.
altTextUp to 125 characters
urlThe logo's link. Must start with http:// or https://
descriptionUp to 500 characters
captionUp to 200 characters. Comes from the attachment.
categoriesArray of plain category names (up to 20, 80 characters each). Used by the Ajax Live Filter.
orderPosition in the list, starting at 0
additionalInfoFile name, MIME type, size and dimensions, shown in the popup
createdAt, updatedAtISO dates

Categories are just names stored on each logo. There's no separate category list for blocks: a block's categories are whatever its logos carry.

Example block markup ​

A Carousel with three logos, five columns on desktop and autoplay off:

html
<!-- wp:sp-logo-carousel/carousel {"uniqueId":"lcpro-carousel-k3x9q2m7a","align":"wide","logoSource":{"mode":"","patternId":"","items":[{"id":"logo-1","mediaId":"101","title":"Northwind","altText":"Northwind logo","url":"https://northwind.example","categories":["Partners"],"order":0},{"id":"logo-2","mediaId":"102","title":"Contoso","altText":"Contoso logo","url":"","categories":["Clients"],"order":1},{"id":"logo-3","mediaId":"103","title":"Fabrikam","altText":"Fabrikam logo","url":"","categories":["Clients"],"order":2}]},"layout":{"carouselStyle":"standard","shared":{"autoplay":false},"standard":{"columns":{"device":{"Desktop":5,"Tablet":3,"Mobile":2}}}}} /-->

A Grid with Load More pagination after eight logos:

html
<!-- wp:sp-logo-carousel/grid {"uniqueId":"lcpro-grid-p8d2w4n1c","logoSource":{"mode":"","patternId":"","items":[ … ]},"layout":{"gridStyle":"standard","shared":{"pagination":true}},"gridPagination":{"paginationType":"loadMore","logoShowPerClick":8}} /-->

Generating blocks in PHP ​

php
$items = array();
foreach ( array( 101, 102, 103 ) as $index => $attachment_id ) {
	$items[] = array(
		'id'      => 'logo-' . $attachment_id,
		'mediaId' => (string) $attachment_id,
		'title'   => get_the_title( $attachment_id ),
		'altText' => (string) get_post_meta( $attachment_id, '_wp_attachment_image_alt', true ),
		'order'   => $index,
	);
}

$attrs = array(
	'uniqueId'   => 'lcpro-carousel-' . strtolower( wp_generate_password( 9, false ) ),
	'logoSource' => array(
		'mode'      => '',
		'patternId' => '',
		'items'     => $items,
	),
);

wp_insert_post( array(
	'post_title'   => 'Our clients',
	'post_status'  => 'draft',
	'post_type'    => 'page',
	'post_content' => serialize_block( array(
		'blockName'    => 'sp-logo-carousel/carousel',
		'attrs'        => $attrs,
		'innerBlocks'  => array(),
		'innerHTML'    => '',
		'innerContent' => array(),
	) ),
) );

Rules that save debugging time:

  1. Give every block its own uniqueId. The block's CSS is scoped to it. Two blocks with the same ID on one page share styles. (The editor repairs duplicates when you open the page; generated content that's never opened won't be repaired.)
  2. Leave out what you don't need. Attributes you don't send use their defaults.
  3. Copy a whole group rather than guessing keys. The surest way is to configure one block by hand, open the Code editor, and copy the group you need. Unknown keys are ignored, so a misspelt key fails silently.
  4. Use mediaId for images. Images resolve from the attachment at render time, so a logo picks up the right size and survives a domain change. imageUrl alone works, but loses those benefits.

Reading the real defaults ​

Defaults shift between releases, so read them from your own install with WP-CLI:

bash
wp eval '
$type = WP_Block_Type_Registry::get_instance()->get_registered( "sp-logo-carousel/grid" );
echo wp_json_encode( $type->attributes["layout"]["default"], JSON_PRETTY_PRINT );
'

Swap the block name and the attribute key (imagesSettings, gridPagination, …) to explore.

Saved Templates are usually the better tool

If the goal is "the same logos in many places," build it once as a Saved Template and place [lc_template id="…"] wherever you need it. One place to update, and no attribute JSON to maintain.

Next steps ​