Freeform landing template with Pinned Data

View as Markdown
Last updated September 14, 2026

A complete walkthrough for the most common Freeform use case: a campaign landing template that assembles content from several entries and a dynamic query, with no single connected content type behind it.

You'll build:

  • A Freeform template at /campaigns/spring-2026
  • One Pinned Entry providing the template-level hero
  • One Pinned Query pulling the current top 3 products
  • Reusable sections binding to both sources
  • Lives at a real route on your site

Prerequisite: Enable Freeform Feature is on in your Studio project (Enabling Freeform). If you haven't enabled it, do that first. The Design and Data tabs both disappear without it, so the Additional Entry Data / Queries sections you'll need below are unreachable.

The setup

Two existing content types in your stack:

Click to enlarge

A campaign entry exists with a hero ready to go. Multiple product entries exist. Some have featured: true.

Step 1: Create the Freeform template

  1. In Compositions, open the Templates tab and select + New Template
  2. In the create dialog, pick Freeform (not "Connected Template")
  3. Name it spring_2026_campaign

Studio opens a canvas with the FREEFORM MODE badge in the top bar and an empty canvas with setup helpers: "Add Components To Canvas, Pin Data".

Click to enlarge

Step 2: Set the URL

Click the URL editor (pencil icon in the canvas toolbar). The Edit URL modal opens with the default Freeform pattern:

{{composition_uid}}

Replace it with a clean campaign URL:

/campaigns/spring-2026

Save. Studio reloads the iframe at the new path.

Click to enlarge

Detail: Freeform templates: URL pattern

Step 3: Pin the campaign entry

  1. In the right panel, open the Data tab and find the Additional Entry Data section
  2. Click Link Entry
  3. In the search dialog, pick the campaign content type
  4. Search for "Spring 2026", then confirm

The pinned entry appears in the list. Studio gives it a binding handle you can use anywhere on the template.

Click to enlarge

Click to enlarge

Step 4: Pin the products query

  1. In the Data tab, find the Pinned Queries section
  2. Click Create Query
  3. Configure:

    • Content type: product
    • Filter: featured = true
    • Order by: price ascending
    • Limit: 3
  4. Save the pin

The query result is now bindable from any Repeater on the template.

Click to enlarge

Step 5: Add a hero section bound to the pinned campaign

If you already have a landing_hero section (built in the overrides recipe), drop it. Otherwise build one inline:

  1. Drop a Box at the root and style it as a hero
  2. Inside:

    • Heading, bind text to Pinned Entry → Spring 2026 → headline
    • Text, bind to Pinned Entry → Spring 2026 → subhead
    • Image, bind src to Pinned Entry → Spring 2026 → hero_image
    • Button, bind href to Pinned Entry → Spring 2026 → primary_cta

Studio's data picker shows pinned entries alongside template and other data sources.

Step 6: Add the products grid bound to the pinned query

Below the hero:

  1. Drop a Heading, text: "Featured products"
  2. Drop a Box with a grid layout
  3. Inside the Box, drop a Repeater
  4. Bind the Repeater's source to the Featured Products pinned query
  5. Inside the Repeater, drop a Box (the card frame), and inside that:

    • Image, bind to repeater.image (picker root: Repeater Data)
    • Heading, bind to repeater.name
    • Text, bind to repeater.price (your component can format it)
    • Button, bind href to repeater.url

The Repeater iterates the query result: repeater.* (Repeater Data) refers to the current iteration item (a product entry). The SDK marks these as RepeaterBindingValue, distinct from template-level bindings.

Alternative: if you have a product_card section (built in the card-grid recipe) anchored on a product-shaped Global Field, drop it inside the Repeater instead. Studio scope-root matches it against the iteration item.

Step 7: Save and view

Save the composition.

Click to enlarge

Open http://localhost:3000/campaigns/spring-2026 in your browser.

You should see:

Click to enlarge

The hero is bound to the campaign entry. The grid auto-refreshes whenever the underlying products query result changes. Publish a new featured product and it shows up here on next render.

What this produces

  • No new content type needed. You didn't model "campaign landing template" as a CT. You composed it from existing entries.
  • The query stays live. Marketing publishes a new featured product, and it appears on this template automatically.
  • One section can serve many templates. The card layout you built here works on any other Freeform or Connected template that pins products.
  • Per-template branding. This template can use one hero design. The next campaign uses a completely different layout (both Freeform, no shared CT constraint).

Common patterns

One pinned entry for template metadata + N pinned queries for content. A campaign template pins the campaign entry (title, headline, theme image), plus queries for featured items, top stories, related links.

Multiple pinned entries assembled into one template. Pin a hero entry, a testimonial entry, and a CTA entry. Compose them into a single template where each section binds to its own pinned entry.

A "compare" template with two pinned entries side by side. Pin two products. Build a side-by-side layout. The same template works for any pair you choose.

When Freeform is NOT the right choice

SymptomBetter choice
Every campaign has the same structure with different contentBuild a campaign content type, use a Connected template
You're modelling repeating, content-driven templatesConnected template
The template is content-driven enough to deserve a CTConnected template
You'd be making the same Freeform composition over and overConnected template

Freeform is for genuinely one-off templates. If you find yourself copying a Freeform composition to make a similar one, that's a signal. Make a content type instead.

See also