Skip to main content
BeyondWords can usually detect content segments on your page automatically. When segment detection is working correctly, the following player features can be enabled in your project (Distribution → Player → Settings) without any additional integration:
  • Highlight paragraphs: Highlight the paragraph currently being read aloud, helping users follow along with the audio
  • Highlight words: Highlight individual words as they are spoken, creating an immersion reading experience
  • Playback from paragraphs: Allow users to click or tap a paragraph to begin playback from that point
In some cases, however, the structure of your website or app may prevent the player from detecting segments correctly. The following sections explain how to implement segment detection manually for JavaScript, iOS, and Android.

JavaScript

If you’re using the JavaScript player and segment detection isn’t working properly, you can add markers to elements on your page to improve detection accuracy:
<h1 data-beyondwords-marker="1af51b2a-72df-4b86-bb7c-87d057231ca0">
  This is the title.
</h1>

<p data-beyondwords-marker="5d2c6eba-f612-45c7-b987-00fde473d867">
  This is the first paragraph.
</p>

<p data-beyondwords-marker="d89257cd-ff53-476e-aef2-84dadcca1cc5">
  This is the second paragraph.
</p>

Markers

If you add markers manually, we recommend using randomly generated UUIDs. Markers must be stable and should not change between page refreshes.
  • If you’re using the client-side integration, markers will be automatically retrieved from your page when content is processed
  • If you’re sending HTML to the BeyondWords API, markers will be automatically extracted from the HTML when content is processed
  • If you’re sending plaintext to the BeyondWords API, you will need to set the marker attribute on each segment alongside the text
If a segment marker is not provided, BeyondWords will generate one for you. You can retrieve these from the Get content endpoint (use ?segments=full) and add them to the HTML of your article. We recommend generating UUIDs as markers to avoid duplicates, in case there are multiple players on the same page.

How it works

Once the player script has loaded, it adds global listeners to your page to detect click and mousemove events. When a user hovers over or clicks on an element, the player attempts to match that element against segments using markers (see above), xpath, or an MD5 fingerprint of the text content. If a match is found, the player emits HoveredSegmentUpdated and PressedSegment events. Additionally, when the currentTime of the media updates (e.g., during playback), the player emits a CurrentSegmentUpdated event. These events are used to highlight segments on the page and control playback—for example, by setting currentTime to the startTime of the segment the user clicked on. The currentSegment and hoveredSegment properties of the player are also updated accordingly. To highlight segments, the player wraps the segment content in a <mark> element with custom styles. The mark is removed once highlighting ends. To avoid interfering with your page, highlighting and click handling are disabled when hovering over a link or an element with a click or mousedown handler. Note that this does not apply to event listeners (see below).

Event listeners

The player cannot detect event listeners registered on elements within a segment. For example, the button below does not have an onclick property, so playback will be affected when it is clicked:
<p data-beyondwords-marker="5d2c6eba-f612-45c7-b987-00fde473d867">
  This is the first paragraph. <button id="my-button"></button>
</p>

<script>
  document.getElementById("my-button").addEventListener("click", event => {
    console.log("The button was clicked.");
  });
</script>
To prevent this, call event.preventDefault() at the top of the event listener:
<script>
  document.getElementById("my-button").addEventListener("click", event => {
    event.preventDefault();
    console.log("The button was clicked.");
  });
</script>
This will prevent the player from changing its current time when the button is clicked.

Configuration

Playback from paragraphs can be configured using the following player properties:
PropertyDescription
highlightColorSet a custom highlight color for segments
highlightSectionsControl which segments highlighting applies to
clickableSectionsControl which segments can be clicked on
segmentWidgetSectionsControl which segments the widget appears next to
segmentWidgetPositionControl which side the widget appears next to the segment
currentSegmentGet the current segment (read-only)
hoveredSegmentGet the hovered segment (read-only)

Mobile SDKs

The mobile SDK implementations are based on the JavaScript version above. Unlike the JavaScript player, the mobile SDKs cannot automatically identify segments—you will need to manually link each text segment to its BeyondWords marker.
You can find a full example of playback from paragraphs integration in the Android GitHub repository:

Highlighting the current segment

Listen for the CurrentSegmentUpdated event, then find the corresponding UI element and apply your desired styling:
object : EventListener {
    override fun onEvent(event: PlayerEvent, settings: PlayerSettings) {
        if (event.type == "CurrentSegmentUpdated") {
            val text = segments[settings.currentSegment?.marker]
            for (i in 0 until contentView.childCount) {
                val view = contentView.getChildAt(i)
                if (view !is TextView) continue
                if (view.text == text) {
                    view.setBackgroundColor(android.graphics.Color.LTGRAY)
                } else {
                    view.setBackgroundColor(android.graphics.Color.TRANSPARENT)
                }
            }
        }
    }
}

Handling segment clicks

Set a View.OnClickListener and call setCurrentSegment with the corresponding marker:
fun onSegmentClick(segmentText: TextView) {
    val marker = segments.entries.firstOrNull { it.value == segmentText.text }?.key ?: return
    playerView.setCurrentSegment(segmentMarker = marker)
}