Skip to main content
Veles generates branded proposals, order forms, and contracts directly from quote data. You build templates in Microsoft Word (DOCX) or Google Docs/Slides, insert merge fields that reference quote variables, and Veles renders the final document with live deal data at generation time. Templates are managed by admins and available to reps when generating documents from a quote. The output reflects your brand identity (logo, colors) and can include pricing tables, terms, CRM data, and any content from the quote’s blocks.

Supported formats

FormatTemplateOutputNotes
DOCX (Microsoft Word).docx file with merge fieldsPDF or DOCXUses Word’s MERGEFIELD syntax. Most flexible for complex layouts.
Google DocsGoogle Doc with template tagsPDF or Google DocUses {{ }} handlebars syntax. Easier to collaborate on templates.
Google SlidesGoogle Slide deck with template tagsPDF or Google SlidesSame {{ }} syntax. Best for visual proposals and pitch decks.

Template syntax

Inserting merge fields

  1. Place your cursor where you want the dynamic value.
  2. Press Ctrl+F9 (Windows) or Cmd+F9 (Mac) to create field brackets { }.
  3. Type the MERGEFIELD syntax between the brackets.
  4. Press Cmd+Shift+Option+U to save the merge field.
  5. Use Alt+F9 (Windows) or Option+F9 (Mac) to toggle between field codes and rendered values.
Alternative: Insert → Quick Parts → Field → choose “MergeField” from the list.

Syntax reference

OperationSyntax
Simple valueMERGEFIELD =title \* MERGEFORMAT
Nested valueMERGEFIELD =owner.name \* MERGEFORMAT
Loop startMERGEFIELD options:each(option) \* MERGEFORMAT
Loop variableMERGEFIELD =option.name \* MERGEFORMAT
Loop endMERGEFIELD options:endEach \* MERGEFORMAT
Conditional startMERGEFIELD salesforce:if \* MERGEFORMAT
Conditional endMERGEFIELD salesforce:endIf \* MERGEFORMAT
Boolean conditionalMERGEFIELD block:if(is_option) \* MERGEFORMAT

Template variables reference

Every variable below is available in all template formats. Use dot notation to access nested values (e.g., owner.name, line.formatted.price).

Top-level fields

VariableTypeDescription
titleStringThe quote/opportunity title.
logoImageCompany logo from your brand settings.
terms_htmlHTMLCombined HTML from all Terms and Text blocks. Nullable.
blocksArrayAll quote blocks in order (title, terms, options, text). See Blocks.
optionsArrayPricing Option blocks only. See Options.
primary_optionObjectThe primary option (nullable if none set). Same structure as an option.

Owner (sales rep)

Access via owner.*.
VariableTypeDescriptionExample
owner.nameStringFull name”Michael Scott”
owner.emailStringEmail addressmichael@company.com
owner.phoneStringPhone number”(555) 123-4567”
owner.job_titleStringJob title”Regional Manager”

Title block

Access via title_block.* or when iterating blocks with is_title.
VariableTypeDescription
title_block.nameStringQuote name.
title_block.fromStringFrom company name.
title_block.prepared_byStringPreparer name.
title_block.prepared_by_extraStringPreparer additional info (title, email).
title_block.forStringRecipient company name.
title_block.for_extraStringRecipient additional info.
title_block.issued_onDateIssue date (e.g., “January 15, 2025”).
title_block.valid_untilDateExpiry date.

Blocks

The blocks array contains all blocks in the quote, in display order. Since blocks are polymorphic (they can be different types), use the type flags to conditionally render content.
FlagTrue when
is_titleTitle block (cover page data).
is_termsTerms or aggregated terms block.
is_optionPricing Option block.
is_textText block (free-form content).
Each block also has terms_html (for Terms/Text blocks) and name (for Title/Option blocks).

Options

Access via the options array, primary_option, or when iterating blocks with is_option. Each option contains:
VariableTypeDescriptionExample
option.nameStringOption name.”Enterprise Plan”
option.frequencyStringBilling frequency.”annual”, “monthly”, “quarterly”
option.year_countIntegerNumber of calculation periods.3
option.formatted_contract_lengthStringHuman-readable contract length.”3 years”
option.total_valueStringRaw decimal total.”150000.00”
option.formatted_total_valueCurrencyFormatted total.”$150,000.00”
option.currencyStringCurrency code.”USD”
option.start_dateDateFirst calculation start.”January 1, 2025”
option.end_dateDateLast calculation end.”December 31, 2027”
option.service_start_dateDateService start date (nullable).
option.upliftStringAnnual uplift percentage (nullable).“3%“
option.custom_fieldsHashOption-level custom fields (dynamic keys).
option.terms_htmlHTMLTerms specific to this option (nullable).
option.calculationsArrayOne per billing period. See Calculations.

Calculations (periods)

Each option contains a calculations array with one entry per billing period (year, quarter, month). Access via option.calculations.
VariableTypeDescriptionExample
calc.yearInteger1-based period number.1
calc.currencyStringCurrency code.”USD”
calc.start_dateDatePeriod start.”January 1, 2025”
calc.end_dateDatePeriod end.”December 31, 2025”
calc.total_discountFloatRaw discount amount.5000.0
calc.creditsStringFormatted credits (abbreviated).“100K”
calc.credits_fullStringFull unscaled credits number.”100000”
calc.credit_rateCurrencyUnit price per credit.
calc.credit_discountStringDiscount on credits.
calc.credit_totalCurrencyCredits total formatted.
calc.summaryHashSummary variables (dynamic keys).
calc.uom_fieldsHashUOM field values (dynamic keys).{"seats": "100K"}
calc.custom_columnsHashCustom calculation columns (dynamic keys).
calc.any_one_timeBooleanHas one-time lines?
calc.any_recurringBooleanHas recurring lines?
calc.any_transactionalBooleanHas transactional lines?
calc.linesArrayAll line items. See Line Items.
calc.one_time_linesArrayOne-time lines only.
calc.recurring_linesArrayRecurring lines only.

Formatted totals

Access via calc.formatted.*.
VariableTypeDescriptionExample
calc.formatted.totalCurrencyPeriod total.”$50,000.00”
calc.formatted.original_totalCurrencyPre-discount total.”$55,000.00”
calc.formatted.discountCurrencyDiscount amount.”$5,000.00”
calc.formatted.discount_totalCurrencyTotal discount formatted.
calc.formatted.system_totalCurrencySystem-calculated total.
calc.formatted.system_discountCurrencySystem-calculated discount.

One-time vs. recurring breakout

Access via calc.breakout.*. Both raw numbers and formatted strings are available.
VariableTypeDescription
calc.breakout.one_time_originalFloatRaw one-time original amount.
calc.breakout.one_time_totalFloatRaw one-time total.
calc.breakout.recurring_originalFloatRaw recurring original amount.
calc.breakout.recurring_totalFloatRaw recurring total.
calc.breakout.formatted_one_time_originalCurrencyOne-time list price.
calc.breakout.formatted_one_time_totalCurrencyOne-time net price.
calc.breakout.formatted_recurring_originalCurrencyRecurring list price.
calc.breakout.formatted_recurring_totalCurrencyRecurring net price.
calc.breakout.formatted_one_time_listCurrencyOne-time list (alternate).
calc.breakout.formatted_one_time_netCurrencyOne-time net (alternate).
calc.breakout.formatted_recurring_listCurrencyRecurring list (alternate).
calc.breakout.formatted_recurring_netCurrencyRecurring net (alternate).

Line items

Access via calc.lines, calc.one_time_lines, or calc.recurring_lines. Each line represents a single product on the quote.
VariableTypeDescriptionExample
line.product_nameStringProduct display name.”Enterprise License”
line.product_skuStringProduct SKU (nullable).
line.categoryStringProduct category (nullable).
line.quantityStringQuantity value.”50”
line.metric_valueStringUOM + scale suffix.”100K”
line.unit_priceFloatRaw unit price.100.0
line.one_timeBooleanIs this a one-time charge?
line.is_transactionalBooleanIs this a transactional charge?
line.proratedBooleanIs this prorated?
line.custom_columnsHashLine-level custom columns (dynamic keys).
line.product_custom_fieldsHashProduct custom fields (dynamic keys).

Formatted line values

Access via line.formatted.*. These are pre-formatted for display.
VariableTypeDescriptionExample
line.formatted.nameStringDisplay name.
line.formatted.original_priceCurrencyList price.”$5,000.00”
line.formatted.priceCurrencyNet price.”$4,500.00”
line.formatted.discountCurrencyDiscount amount.”$500.00”
line.formatted.prorated_priceCurrencyProrated price (if applicable).
line.formatted.unit_priceCurrencyFormatted unit price.”$100.00”
line.formatted.system_priceCurrencySystem-calculated price.
line.formatted.system_price_discountCurrencySystem price discount.

Unit of Measure

Access via line.uom.* (nullable — may not be present on all lines).
VariableTypeDescriptionExample
line.uom.keyStringUOM key.”seats”
line.uom.labelStringUOM display label.”Seats”

Salesforce data

Available when the quote is linked to Salesforce. Always wrap in a conditional since this is null when Salesforce is not connected.
VariableTypeDescription
salesforce.account_nameStringSF account name.
salesforce.account_idStringSF account ID.
salesforce.account_phoneStringAccount phone.
salesforce.account_websiteStringAccount website URL.
salesforce.stageStringOpportunity stage.
salesforce.crm_urlStringLink to Salesforce record.
salesforce.cpq_urlStringLink to Veles CPQ record.
salesforce.last_syncStringLast sync timestamp (ISO 8601).
salesforce.custom_fields.*DynamicCustom fields mapped in Veles. Access via dot notation: salesforce.custom_fields.my_field.

Addresses

Access via salesforce.billing_address.* or salesforce.shipping_address.* (both nullable).
VariableType
*.streetString
*.cityString
*.stateString
*.postal_codeString
*.countryString

Template examples

Cover page (DOCX)

«=title_block.name»

Prepared for: «=title_block.for»
«=title_block.for_extra»

Prepared by: «=title_block.prepared_by»
«=title_block.prepared_by_extra»

Date: «=title_block.issued_on»
Valid until: «=title_block.valid_until»

Iterating through all blocks (DOCX)

Use the type flags to render each block type differently:
«blocks:each(block)»
  «block:if(is_title)»
    «=block.name»
    Prepared by: «=block.prepared_by»
  «block:endIf»

  «block:if(is_option)»
    Option: «=block.name»
    Total: «=block.formatted_total_value»
  «block:endIf»

  «block:if(is_terms)»
    «=block.terms_html»
  «block:endIf»

  «block:if(is_text)»
    «=block.terms_html»
  «block:endIf»
«blocks:endEach»

Pricing options with year-by-year breakdown (DOCX)

«options:each(option)»
  «=option.name» — «=option.formatted_contract_length»
  Total Contract Value: «=option.formatted_total_value»

  «option.calculations:each(calc)»
    Year «=calc.year» («=calc.start_date» – «=calc.end_date»)
    Total: «=calc.formatted.total»

    «calc:if(any_one_time)»
      One-Time Fees: «=calc.breakout.formatted_one_time_total»
    «calc:endIf»

    «calc:if(any_recurring)»
      Recurring: «=calc.breakout.formatted_recurring_total»
    «calc:endIf»
  «option.calculations:endEach»
«options:endEach»

Line items table (DOCX)

«calc.lines:each(line)»
  «=line.formatted.name»  |  «=line.quantity»  |  «=line.formatted.unit_price»  |  «=line.formatted.price»
«calc.lines:endEach»

Separate one-time and recurring tables (DOCX)

«calc:if(any_recurring)»
  Recurring Charges:
  «calc.recurring_lines:each(line)»
    «=line.formatted.name»  |  «=line.quantity»  |  «=line.formatted.price»
  «calc.recurring_lines:endEach»
  Recurring Total: «=calc.breakout.formatted_recurring_total»
«calc:endIf»

«calc:if(any_one_time)»
  One-Time Charges:
  «calc.one_time_lines:each(line)»
    «=line.formatted.name»  |  «=line.formatted.price»
  «calc.one_time_lines:endEach»
  One-Time Total: «=calc.breakout.formatted_one_time_total»
«calc:endIf»

Salesforce customer info with conditional (DOCX)

«salesforce:if»
  Customer: «=salesforce.account_name»
  «=salesforce.billing_address.street»
  «=salesforce.billing_address.city», «=salesforce.billing_address.state» «=salesforce.billing_address.postal_code»
«salesforce:endIf»

Full proposal (Google Docs)

{{ title_block.name }}

Prepared for: {{ title_block.for }}
Prepared by: {{ title_block.prepared_by }}
Date: {{ title_block.issued_on }}

{{ #each(options) as option }}
Option: {{ option.name }}
Contract Length: {{ option.formatted_contract_length }}
Total: {{ option.formatted_total_value }}

{{ #each(option.calculations) as calc }}
Year {{ calc.year }}:
{{ #each(calc.lines) as line }}
  - {{ line.formatted.name }}: {{ line.quantity }} × {{ line.formatted.unit_price }} = {{ line.formatted.price }}
{{ /each }}
Period Total: {{ calc.formatted.total }}
{{ /each }}
{{ /each }}

{{ #if(salesforce) }}
Customer: {{ salesforce.account_name }}
{{ /if }}

Dynamic hash fields

Several variables use dynamic keys (marked as “Hash” in the reference). These include custom_fields, custom_columns, summary, uom_fields, and product_custom_fields. Access dynamic fields with dot notation using the field key:
«=option.custom_fields.my_custom_field»
«=calc.custom_columns.my_column»
«=salesforce.custom_fields.my_sf_field»
«=line.product_custom_fields.my_product_field»
The available keys depend on what custom fields you’ve configured in the Object Explorer, Display Options, and CRM field mapping.

Tips

Use formatted values for display. Most numeric fields have both a raw value (e.g., line.unit_price = 100.0) and a formatted version (e.g., line.formatted.unit_price = "$100.00"). Use the formatted versions in templates to get proper currency formatting without manual work. Always wrap Salesforce data in conditionals. The salesforce object is null when no CRM is connected. Referencing salesforce.account_name without a conditional will produce an error in the generated document. Use one_time_lines and recurring_lines for split tables. Instead of looping through all lines and checking the one_time flag on each, use the pre-filtered arrays for cleaner templates. Test with a real quote. Generate a document from an actual quote to verify all merge fields resolve correctly. Nullable fields, empty arrays, and missing custom fields are the most common causes of template errors.

What’s next

Account Setup

Configure the logo and brand color that appear in generated documents.

Quote Overview

Understand the quote structure that document generation renders from.

Display Options

Control what pricing detail appears in generated documents.

Web Portal

Share interactive proposals alongside generated documents.