---
title: "Bet Share"
canonical_url: "https://apidocs.sportradar.com/resources/virtual-stadium/docs/web/widgets/virtualStadium/features/betShare"
markdown_url: "https://apidocs.sportradar.com/resources/virtual-stadium/docs/web/widgets/virtualStadium/features/betShare.md"
last_updated: "2026-09-14T11:55:40Z"
---

# Bet Share

![Bet Share Demo](https://apidocs.sportradar.com/resources/virtual-stadium/static/static/gif/bet-share-demo.gif)

The Bet Share module is a centralized hub for sharing and discovering bets within Virtual Stadium. It allows users to view all shared bets, contribute new ones, and revisit their previously shared bets. This feature enhances community engagement and provides social betting experiences.

## Overview

The Bet Share module enables:

- **Bet Discovery** - Browse bets shared by other community members
- **Bet Sharing** - Share your own bets with the community
- **Bet History** - Access your previously shared bets
- **Social Interaction** - Engage with other bettors around shared bets

This module requires adapter integration to function properly and provide betting data.

The bet-share picker loads the user's placed tickets via the adapter `tickets` endpoint. The same contract powers **Central Hub** share-betslip screens. The widget auto-detects the delivery mode from the first response:

- **Non-paginated** — **you** call `callback` with the full `tickets` array; everything renders immediately.
- **Paginated** — **you** call `callback` with the first batch (`pageSize`, `hasMore`); the widget fires `onAction` `ticketsFetchMore` when it needs the next page. Central Hub uses the same adapter contract.

See [Adapter integration](#adapter-integration) and [Ticket pagination](#ticket-pagination) below.

***

## Adapter Integration

The Bet Share feature requires adapter integration to function properly. See the appropriate adapter type based on your integration needs:

- [Custom Adapter Implementation](https://apidocs.sportradar.com/resources/virtual-stadium/docs/web/widgets/virtualStadium/features/web/adapter/custom/features/betShare.md)
- [Hosted Adapter Configuration](https://apidocs.sportradar.com/resources/virtual-stadium/docs/web/widgets/virtualStadium/features/web/adapter/hosted/features/betShare.md)

***

### Activating the Copy Bet Button

To enable the copy bet functionality in the shared bets, you must first integrate and configure the **Copy Bet feature**. For detailed implementation instructions, see the [Copy Bet Feature Documentation](https://apidocs.sportradar.com/resources/virtual-stadium/docs/web/widgets/virtualStadium/features/copyBetButton.md).

> **Info**
>
> The copy bet button is **not visible** to the user who originally shared the bet, preventing self-copying and maintaining fair betting practices.

***

## Ticket pagination

When your adapter signals paginated mode (`pageSize` or `hasMore` on the first `tickets` callback), the widget fires `onAction` with type `ticketsFetchMore` when it needs the next page. **You** load the next page from your backend and call the **stored** `callback` from the initial `tickets()` call with `{ newTickets, ... }` — the widget does **not** invoke `tickets()` again and never calls `callback` itself.

```mermaid
sequenceDiagram
  participant Widget as VirtualStadium
  participant Page as EmbedPage_onAction
  participant Adapter as ClientAdapter

  Widget->>Adapter: tickets(args, callback)
  Adapter-->>Widget: callback(undefined, { tickets: [page1], pageSize: 20, hasMore: true, nextCursor: "c1" })
  Note over Widget: Paginated mode detected.

  Widget->>Page: onAction ticketsFetchMore { cursor: "c1" }
  Page->>Adapter: loadMoreTickets("c1")
  Adapter-->>Widget: callback(undefined, { newTickets: [page2], hasMore: false })
  Note over Widget: Appends page 2. End of list.
```

| Step | Who          | Action                                                                                                                        |
| ---- | ------------ | ----------------------------------------------------------------------------------------------------------------------------- |
| 1    | Widget       | Calls adapter `tickets(args, callback)`                                                                                       |
| 2    | Your adapter | Returns first page: `{ tickets, pageSize, hasMore, nextCursor }`                                                              |
| 3    | Widget       | Renders first batch                                                                                                           |
| 4    | Widget       | Needs the next page; fires `onAction({ type: 'ticketsFetchMore', data: { cursor } })`                                         |
| 5    | Embed page   | Calls your backend; invokes the **stored** `callback` with `{ newTickets, hasMore, nextCursor }` (not a new `tickets()` call) |
| 6    | Widget       | Appends tickets; repeats steps 4–5 until `hasMore: false`                                                                     |

For adapter implementation details and copy-pasteable examples, see:

- [Tickets Function reference](https://apidocs.sportradar.com/resources/widgets/docs/adapter/Types.md#tickets-function) — flow diagrams for both options
- [Adapter Tickets Endpoint Example — Track B](https://apidocs.sportradar.com/resources/widgets/docs/tutorials/examples/adapter-tickets-endpoint-example.md#track-b--paginated-large-ticket-histories) — step-by-step paginated tutorial

Non-paginated integrations (full list in one callback) do not require `ticketsFetchMore` handling. See [Track A](https://apidocs.sportradar.com/resources/widgets/docs/tutorials/examples/adapter-tickets-endpoint-example.md#track-a--non-paginated-recommended-for-getting-started).

***

## Tracking Actions

The Bet Share module triggers various **actions** that can be handled through the `onAction` callback function for analytics, pagination, and user behavior monitoring.

### BetslipShareListOpen

Triggered when a user opens the bet share list interface.

**`type`** `string` ***required***

Action type: `"BetslipShareListOpen"`.

**`data`** `object` ***required***

Action data containing channel information.

**`data.channelId`** `string` ***required***

Unique identifier of the chat channel.

### BetslipShareListClose

Triggered when a user closes the bet share list interface.

**`type`** `string` ***required***

Action type: `"BetslipShareListClose"`.

**`data`** `object` ***required***

Action data with scope information.

**`data.channelId`** `string` ***required***

Unique identifier of the chat channel.

**`data.scope`** `string` ***required***

Scope identifier: `"chat:betshare:list"`.

### BetslipShareListBack

Triggered when a user clicks the back button within the bet share interface.

**`type`** `string` ***required***

Action type: `"BetslipShareListBack"`.

**`data`** `object` ***required***

Action data containing channel information.

**`data.channelId`** `string` ***required***

Unique identifier of the chat channel.

### BetslipShareListDisabled

Triggered when a user attempts to open bet share but the feature is disabled.

**`type`** `string` ***required***

Action type: `"BetslipShareListDisabled"`.

**`data`** `object` ***required***

Action data containing channel information.

**`data.channelId`** `string` ***required***

Unique identifier of the chat channel.

### ticketsFetchMore

Triggered when the bet-share picker needs the next page of tickets. Only fired when your adapter returned `pageSize` or `hasMore: true` on the initial `tickets` callback (paginated mode).

**`type`** `string` ***required***

Action type: `"ticketsFetchMore"`.

**`data`** `object` ***optional***

**`data.cursor`** `string` ***optional***

Opaque cursor from the previous [`TicketResponseV2`](https://apidocs.sportradar.com/resources/widgets/docs/adapter/Types.md#ticketresponsev2) `nextCursor` field. Pass it to your backend to fetch the next batch, then call the **stored** `callback` with `{ newTickets, hasMore?, nextCursor? }`.

***Handling Bet Share Actions:***

```javascript
// Configure onAction callback to handle bet share events
SIR('addWidget', '#virtual-stadium-container', 'virtualStadium', {
    jwt: 'your-jwt-token',
    channelId: 'your-channel-id',
    onAction: function(action) {
        switch(action.type) {
            case 'BetslipShareListOpen':
                // Optional: Log for debugging
                // console.log('Bet share list opened for channel:', action.data.channelId);
                // Track analytics event
                analytics.track('bet_share_opened', {
                    channelId: action.data.channelId
                });
                break;

            case 'BetslipShareListClose':
                // Optional: Log for debugging
                // console.log('Bet share list closed for channel:', action.data.channelId);
                // Track analytics event
                analytics.track('bet_share_closed', {
                    channelId: action.data.channelId,
                    scope: action.data.scope
                });
                break;

            case 'BetslipShareListBack':
                // Optional: Log for debugging
                // console.log('User navigated back in bet share');
                // Track analytics event
                analytics.track('bet_share_back', {
                    channelId: action.data.channelId
                });
                break;

            case 'BetslipShareListDisabled':
                // Optional: Log for debugging
                // console.log('Bet share attempted but disabled');
                // Track analytics event
                analytics.track('bet_share_disabled', {
                    channelId: action.data.channelId
                });
                break;

            case 'ticketsFetchMore':
                // Paginated ticket loading — load next batch and push on the
                // stored tickets callback. See Track B tutorial.
                loadMoreTickets(action.data?.cursor);
                break;
        }
    }
});
```

***

## Customization

**`shareNewBetButtonPosition`** `'top' | 'bottom'` ***optional***

Controls position of the "Share New Bet" button. Default is 'top'.

![share new bet button top position](https://apidocs.sportradar.com/resources/virtual-stadium/static/static/img/share-new-bet-button-top.png)

![share new bet button bottom position](https://apidocs.sportradar.com/resources/virtual-stadium/static/static/img/share-new-bet-button-bottom.png)

***Share New Bet Button Position Configuration:***

```javascript
// Configure the position of the share new bet button
SIR('addWidget', '#virtual-stadium-container', 'virtualStadium', {
    jwt: 'your-jwt-token',
    channelId: 'your-channel-id',
    shareNewBetButtonPosition: 'bottom' // or 'top'
});
```

</div>
</div>

***
