Additional Placement Features for CRM_XXX_DETAIL_ACTIVITY, CRM_DYNAMIC_XXX_DETAIL_ACTIVITY

Choose a tool for developing with an AI agent:

  • use Alaio Vibecode to build an app for Bitrix24 from a task description without knowing any programming language. The agent writes the code and deploys the app to a server, with no manual hosting setup
  • use the MCP server to develop a REST API integration in your own project. The agent refers to the official REST documentation

Scope: placement, crm

Who can work with the widget: a user with access permission to modify the CRM object

The CRM_XXX_DETAIL_ACTIVITY and CRM_DYNAMIC_XXX_DETAIL_ACTIVITY placements add an application item above the timeline in a CRM item form. Instead of a custom interface in an iframe, the application can display the standard Bitrix24 interface in this item: text, links, input fields, lists, and buttons.

To register the widget, use the placement.bind method. The basic capabilities of the placement are described in the article Button Above the Timeline of the CRM object.

Download an example application using this placement.

Widget Location

Placement Code

Location

CRM_XXX_DETAIL_ACTIVITY

An item above the timeline in a standard CRM object form. Replace XXX with the object type, for example, DEAL

CRM_DYNAMIC_XXX_DETAIL_ACTIVITY

An item above the timeline in a custom CRM object type form. Replace XXX with the numeric object type identifier

The user opens the application item in the object form. If useBuiltInInterface: Y was passed during registration, the application first loads in a hidden iframe and then builds the interface by calling setLayout.

OPTIONS Parameter

The built-in interface is enabled by the useBuiltInInterface parameter when the placement is registered. The full list of the OPTIONS parameters is described on the Button Above the Timeline of the CRM_XXX_DETAIL_ACTIVITY, CRM_DYNAMIC_XXX_DETAIL_ACTIVITY Card page.

When useBuiltInInterface = Y, the interface is built from the LayoutDto structure, and the process of working with it is described below.

Handler Data

When the application loads, Bitrix24 passes the current item context in placementOptions:

{
          "entityTypeId": 2,
          "entityId": 123,
          "useBuiltInInterface": "Y"
        }
        

Field
type

Description

entityTypeId
integer

CRM object type identifier

entityId
integer

Identifier of the CRM item whose form contains the open widget

useBuiltInInterface
string

Indicates whether the standard interface is used. For the scenario described on this page, the value is Y

Registration Example

BX24.callMethod(
          'placement.bind',
          {
            'PLACEMENT': 'CRM_DEAL_DETAIL_ACTIVITY',
            'HANDLER': 'https://your-handler-uri.com',
            'TITLE': 'My Widget',
            'OPTIONS': {
              'useBuiltInInterface': 'Y',
              'newUserNotificationTitle': 'Welcome to the new application',
              'newUserNotificationText': 'E-invoice will help you manage invoices'
            }
          }
        );
        

Working with the Widget Interface

Interaction occurs through the method BX24.placement.call. The application workflow when using the standard Bitrix24 interface useBuiltInInterface = Y:

  1. Loading the iframe.

    The application is loaded in a hidden iframe. The placementOptions include:

    • entityTypeId
    • entityId
    • useBuiltInInterface: Y
  2. Rendering the interface.

    Once the application is loaded, it should call setLayout to render the initial state of the widget.

    BX24.placement.call('setLayout', LayoutDto, callback);
            
  3. Responding to actions.

    If the application displays interactive elements in the interface, such as links, it can register a handler bindLayoutEventCallback to handle interactions with those elements.

    BX24.placement.call('bindLayoutEventCallback', null, callback);
            
  4. Managing element states.

    You can change the appearance and visibility of a specific interface element through setLayoutItemState.

    BX24.placement.call('setLayoutItemState', { id: '...', visible: true/false, properties: {...} }, callback);
            
  5. Managing buttons.

    You can change the appearance of the buttons at the bottom of the interface through setPrimaryButtonState and setSecondaryButtonState.

    BX24.placement.call('setPrimaryButtonState', {...}, callback);
            BX24.placement.call('setSecondaryButtonState', {...}, callback);
            
  6. Completing the process.

    When the user's interaction with the widget is complete or if the user clicks "cancel," you need to call finish. The timeline will switch to the default tab.

    BX24.placement.call('finish');
            
  7. Locking the interface.

    During long operations, such as saving, the interface can be locked by calling lock. To unlock, call unlock.

    BX24.placement.call('lock');   // lock
            BX24.placement.call('unlock'); // unlock
            
  8. Tracking changes to the entity.

    To track changes to the entity fields, for example, to redraw the interface based on the field value, you can register a handler bindEntityUpdateCallback. The callback will be invoked immediately after the fields are saved in the editor.

    BX24.placement.call('bindEntityUpdateCallback', null, callback);
            

Interface Appearance LayoutDto

Name
type

Description

blocks
ContentBlockDto[]

Associative array of objects describing content blocks. The array keys are block identifiers

primaryButton
ButtonDto

Primary button. Usually completes data processing, saves it

secondaryButton
ButtonDto

Secondary button. Usually cancels the data processing

Clicking on active buttons triggers callbacks:

  • primaryButton — callback BX24.placement.call('bindPrimaryButtonClickCallback', null, callback)
  • secondaryButton — callback BX24.placement.call('bindSecondaryButtonClickCallback', null, callback)

ContentBlockDto

Content blocks in the main area can be combined and flexibly assembled into various interfaces.

General structure of a block:

{
          "type": "string",
          "visible": true,
          "properties": {}
        }
        
  • type — type of the block, string,
  • visible — controls the visibility of the block, boolean field. Changing visibility allows for dynamic interfaces. Default = true.
  • properties — set of properties for a specific block.

Types of Content Blocks

Type Name
text Text
link Link
withTitle Block with Title
lineOfBlocks Multiple Content Blocks in One Line
dropdownMenu Dropdown Menu
input Text Input Field
textarea Multiline Text Input Field
select Input Field with List Selection
list Unordered List
section Section

Text

A block displaying formatted text.

Required parameters are marked with *

Name
type

Description

value*
string | double

Text or number

multiline
boolean

Line break handling. If true, \n characters will be replaced with <br>. Default is false

bold
boolean

Bold text. Default is false

size
string

Text size. Available values:

  • xs,
  • sm,
  • md — default,
  • lg,
  • xl

color
string

Text color. Available values:

  • base_50,
  • base_60,
  • base_70,
  • base_90,
  • primary,
  • warning,
  • danger,
  • success
{
          "type": "text",
          "properties": {
            "value": "Hello!\nWe are starting.",
            "multiline": true,
            "bold": true,
            "size": "lg",
            "color": "base_90"
          }
        }
        

text

Required parameters are marked with *

Name
type

Description

text*
string

Link text, HTML tags are not supported

action*
ActionDto

Action on clicking the link

size
string

Text size. Available values:

  • xs,
  • sm,
  • md — default,
  • lg,
  • xl

bold
boolean

Bold text. Default is false

{
          "type": "link",
          "properties": {
            "text": "Open Deal",
            "action": { "type": "redirect", "value": "/crm/deal/details/123/" },
            "bold": true
          }
        }
        

link

Block with Title

The block displays a title and a value. Another content block can be used as the value.

Required parameters are marked with *

Name
type

Description

title*
string

Title text

inline
boolean

Show title and value in one line. Default is false

titleWidth
string

Title width, applied if inline=true. Available values:

  • sm,
  • md — default,
  • lg

block*
ContentBlockDto

Content block that serves as the value. Blocks of types text, link, lineOfBlocks are supported

Example with a text content block:

{
          "type": "withTitle",
          "properties": {
            "title": "Title",
            "block": {
              "type": "text",
              "properties": {
                "value": "Some value"
              }
            }
          }
        }
        

withTitle1

Example with a link content block:

{
          "type": "withTitle",
          "properties": {
            "title": "Title 2",
            "block": {
              "type": "link",
              "properties": {
                "text": "Open Deal",
                "action": {
                  "type": "redirect",
                  "value": "/crm/deal/details/123/"
                }
              }
            },
            "inline": true
          }
        }
        

withTitle2

Multiple Content Blocks in One Line

The block displays multiple content blocks of type text, link, or dropdown list in one line. This allows displaying text with different formatting, links, and lists in a single line.

Required parameters are marked with *

Name
type

Description

blocks*
ContentBlockDto[]

Associative array of content blocks. Blocks of types text, link, and dropdownMenu are supported

{
          "type": "lineOfBlocks",
          "properties": {
            "blocks": {
              "text": {
                "type": "text",
                "properties": {
                  "value": "Some text"
                }
              },
              "link": {
                "type": "link",
                "properties": {
                  "text": "link",
                  "action": {
                    "type": "redirect",
                  "value": "/crm/deal/details/123/"
                  }
                }
              },
              "boldText": {
                "type": "text",
                "properties": {
                  "value": "bold text",
                  "bold": true
                }
              }
            }
          }
        }
        

lineOfBlocks

Required parameters are marked with *

Name
type

Description

selectedValue
string

Current selected value. If not filled, the first value from the list will be used

values*
object

An object where the property names are the code of the value option vendor, and the property values are the values that the user will see supplier

{
          "type": "dropdownMenu",
          "properties": {
            "selectedValue": "client",
            "values": {
              "": "- not selected -",
              "supplier": "supplier",
              "client": "client"
            }
          }
        }
        

dropdownMenu

To track value changes, register a callback:

  • BX24.placement.call('bindValueChangeCallback', null, Callback) to receive changes in any of the blocks
  • BX24.placement.call('bindValueChangeCallback', 'block id', Callback) to receive changes in the value of only that block.

When the value changes, the callback will receive the id of the dropdown block and its current value: {id: "clientMenu", value: "client"}.

Text Input Field

Required parameters are marked with *

Name
type

Description

title
string

Field title

value
string

Field text

placeholder
string

Placeholder. Will be shown if the field is not filled

disabled
boolean

If true is passed, the field will be locked for editing. Default is false

errorText
string

Error message. If a non-empty errorText is passed, the current value of the field did not pass validation. The user will see the error

{
          "type": "input",
          "properties": {
            "value": "aaa@mail.domain",
            "placeholder": "Enter email",
            "title": "Email",
            "errorText": "Invalid value"
          }
        }
        

input

To track value changes, register a callback:

  • BX24.placement.call('bindValueChangeCallback', null, Callback) to receive changes in any of the blocks
  • BX24.placement.call('bindValueChangeCallback', 'block id', Callback) to receive changes in the value of only that block.

When the value changes, the callback will receive the id of the text input field and its current value: {id: "email", value: "aaa@mail.domain"}.

Multiline Text Input Field

Required parameters are marked with *

Name
type

Description

title
string

Field title

value
string

Field text

placeholder
string

Placeholder. Will be shown if the field is not filled

disabled
boolean

If true is passed, the field will be locked for editing. Default is false

errorText
string

Error message. If a non-empty errorText is passed, the current value of the field did not pass validation. The user will see the error

{
          "type": "textarea",
          "properties": {
            "value": "Go through the gate\nTurn left",
            "title": "Additional Information"
          }
        }
        

textarea

To track value changes, register a callback:

  • BX24.placement.call('bindValueChangeCallback', null, Callback) to receive changes in any of the blocks
  • BX24.placement.call('bindValueChangeCallback', 'block id', Callback) to receive changes in the value of only that block.

When the value changes, the callback will receive the id of the text input field and its current value: {id: "description", value: "Go through the gate\nTurn left"}.

Input Field with List Selection

Required parameters are marked with *

Name
type

Description

title
string

Field title

selectedValue
string

Current selected value. If not filled, the first value from the list will be used

values*
object

An object where the property names are the code of the value option nyc, and the property values are the values that the user will see New York

disabled
boolean

If true is passed, the field will be locked for editing. Default is false

errorText
string

Error message. If a non-empty errorText is passed, the current value of the field did not pass validation. The user will see the error

{
          "type": "select",
          "properties": {
            "selectedValue": "la",
            "values": {
              "nyc": "New York",
              "la": "Los Angeles",
              "chi": "Chicago"
            },
            "title": "City"
          }
        }
        

select

To track value changes, register a callback:

  • BX24.placement.call('bindValueChangeCallback', null, Callback) to receive changes in any of the blocks
  • BX24.placement.call('bindValueChangeCallback', 'block id', Callback) to receive changes in the value of only that block.

When the value changes, the callback will receive the id of the field and its current value: {id: "city", value: "nyc"}.

Unordered List

Required parameters are marked with *

Name
type

Description

blocks*
ContentBlockDto[]

Associative array of content blocks. Blocks of types text, link, and lineOfBlocks are supported

{
          "type": "list",
          "properties": {
            "blocks": {
              "li1": {
                "type": "text",
                "properties": {
                  "value": "Import CRM elements without attributes",
                  "color": "base_70"
                }
              },
              "li2": {
                "type": "link",
                "properties": {
                  "text": "Getting Started with CRM",
                  "action": {
                    "type": "layoutEvent",
                    "value": "link2ItemClicked!"
                  }
                }
              },
              "li3": {
                "type": "text",
                "properties": {
                  "value": "How to convert a lead",
                  "bold": true,
                  "color": "base_90"
                }
              }
            }
          }
        }
        

list

Section

The block displays a grouped set of blocks. An option with an image is possible.

Required parameters are marked with *

Name
type

Description

blocks*
ContentBlockDto[]

Associative array of content blocks. All block types except section are supported

imageSrc
string

Full path to the image

imageSize
string

Image size. Available values:

  • lg — default,
  • md,
  • sm

type
string

Appearance. Available values:

  • default — default,
  • primary,
  • warning,
  • danger,
  • success,
  • withBorder

Example with multiple blocks and an image:

{
          "type": "section",
          "properties": {
            "type": "withBorder",
            "imageSrc": "https://www.example.com/images/content/products/box/bus.png",
            "blocks": {
              "header": {
                "type": "text",
                "properties": {
                  "value": " Send the client a link to the meeting",
                  "size": "xl",
                  "color": "base_90"
                }
              },
              "notes": {
                "type": "list",
                "properties": {
                  "blocks": {
                    "li1": {
                      "type": "text",
                      "properties": {
                        "value": "The client will choose a convenient slot",
                        "color": "base_70"
                      }
                    },
                    "li2": {
                      "type": "text",
                      "properties": {
                        "value": "The meeting will appear in your tasks",
                        "color": "base_70"
                      }
                    }
                  }
                }
              },
              "howto": {
                "type": "link",
                "properties": {
                  "text": "How does it work?",
                  "action": {
                    "type": "openRestApp",
                    "value": "howto"
                  }
                }
              }
            }
          }
        }
        

section

Example with one block without an image:

{
        	"type": "section",
        	"properties": {
        		"type": "danger",
        		"blocks": {
        			"errorMessage": {
        				"type": "text",
        				"properties": {
        					"value": "An error occurred. Please try again.",
        					"color": "danger"
        				}
        			}
        		}
        	}
        }
        

section2

ButtonDto

A button at the bottom of the interface.

Name
type

Description

title*
string

Button text

state
string

State. Available values:

  • loading — displays a loading indicator
  • disabled

The button is active by default, so the state parameter can be omitted.

ActionDto

An action defines the response to a click on a specific element. Available types of actions:

Redirect

Redirecting is possible in two variants:

  • slider, if it is a relative link to standard Bitrix24 objects that support working in a slider,
  • regular link redirection in other cases.

Required parameters are marked with *

Name
type

Description

type*
const

Action type. Must have the value redirect

value*
string

URI link. For example: https://example.com or /crm/deal/details/1/ for Bitrix24 objects

{
          "type": "redirect",
          "value": "/crm/deal/details/1/"
        }
        

JS Event

Required parameters are marked with *

Name
type

Description

type*
const

Action type. Must have the value layoutEvent

value*
string

Event identifier. For example: doSomething or start_processing

{
          "type": "layoutEvent",
          "value": "clicked"
        }
        

Calling the action triggers the handler registered via BX24.placement.call('bindLayoutEventCallback', null, Callback) or BX24.placement.call('bindLayoutEventCallback', 'block id', Callback).

The handler will receive the value of the action and the id of the block that triggered the action: {id: "myLink", value: "clicked"}.

Opening Application Slider

Calling the action will open the slider of the application that registered the widget. The context will be passed to the slider:

  • entityTypeId — identifier of the object type to which the activity is linked
  • entityId — item identifier

Required parameters are marked with *

Name
type

Description

type*
const

Action type. Must have the value openRestApp

value
object | string

Data to pass to the application slider. A string value is available in the value parameter

sliderParams
ActionSliderParamsDto

Parameters for opening the slider

ActionSliderParamsDto

Name
type

Description

width
integer

Slider width, px. Cannot be used simultaneously with leftBoundary

leftBoundary
integer

Slider full width of the browser window with a left margin, px. Cannot be used simultaneously with width

title
string

Application slider title

labelText
string

Label text in the slider header

labelColor
string

Label text color in the slider header

labelBgColor
string

Label background color in the slider header

{
          "type": "openRestApp",
          "value": {
            "myId": 123,
            "someImportant": "qwerty"
          },
          "sliderParams": {
            "title": "This is the application slider title",
            "width": 700
          }
        }
        

Examples of LayoutDto

{
        	"blocks": {
        		"section1": {
        			"type": "section",
        			"properties": {
        				"type": "withBorder",
        				"imageSrc": "https://www.example.com/images/content/products/box/bus.png",
        				"blocks": {
        					"header": {
        						"type": "text",
        						"properties": {
        							"value": " Send the client a link to the meeting",
        							"size": "xl",
        							"color": "base_90"
        						}
        					},
        					"notes": {
        						"type": "list",
        						"properties": {
        							"blocks": {
        								"li1": {"type": "text", "properties": {"value": "The client will choose a convenient slot", "color": "base_70"}},
        								"li2": {"type": "text", "properties": {"value": "The meeting will appear in your tasks", "color": "base_70"}}
        							}
        						}
        					},
        					"howto": {
        						"type": "link",
        						"properties": {"text": "How does it work?", "action": {"type": "openRestApp", "value": "howto"}}
        					}
        				}
        			}
        		},
        		"section2": {
        			"type": "section",
        			"properties": {
        				"type": "primary",
        				"blocks": {
        					"sectionText": {
        						"type": "lineOfBlocks",
        						"properties": {"blocks": {"block1": {"type": "text", "properties": {"value": "If you haven't tried the sales generator yet, now is the time to test this tool in action", "color": "base_70"}}, "block2": {"type": "link", "properties": {"text": "Learn more", "action": {"type": "redirect", "value": "/crm/"}}}}}
        					}
        				}
        			}
        		}
        	},
        	"primaryButton": {"title": "Enable"},
        	"secondaryButton": {"title": "Cancel"}
        }
        

example1

{
        	"blocks": {
        		"errorMessage": {
        			"type": "text",
        			"properties": {"value": "Use all the capabilities of mobile SMS marketing\nSending SMS is easy to set up and use in CRM Bitrix24\nSend messages directly from the deal, lead, client, invoice, or estimate card.", "size": "sm", "color": "base_70", "multiline": true}
        		},
        		"section1": {
        			"type": "section",
        			"properties": {"type": "danger", "blocks": {"errorMessage": {"type": "text", "properties": {"value": "An error occurred. Please try again", "color": "danger"}}}}
        		}
        	},
        	"primaryButton": {"title": "Enable", "state": "disabled"},
        	"secondaryButton": {"title": "Cancel", "state": "disabled"}
        }
        

example2

{
        	"blocks": {
        		"name": {"type": "input", "properties": {"value": "John", "placeholder": "Enter name", "title": "Name"}},
        		"lastname": {"type": "input", "properties": {"value": "Doe", "placeholder": "", "title": "Last Name"}},
        		"secondname": {"type": "input", "properties": {"value": "", "placeholder": "Enter middle name", "title": "Middle Name"}}
        	},
        	"primaryButton": {"title": "Save"},
        	"secondaryButton": {"title": "Cancel"}
        }
        

example3

Common Errors

Problem

How to Fix It

The application item opens as a regular iframe without the standard interface

Pass useBuiltInInterface: Y in the OPTIONS object when registering the placement

The item is open, but no content appears

After the application loads, call BX24.placement.call('setLayout', LayoutDto, callback) and pass a non-empty blocks object

Clicking a link with the layoutEvent action is not handled

Register a callback using bindLayoutEventCallback. Pass the event identifier in the action's value field

The item remains open after the scenario is complete

Call BX24.placement.call('finish') when the user completes or cancels the action

Continue Exploring