> Documentation index: https://www.gooddata.ai/docs/gooddata-ui/llms.txt lists every page of these docs as Markdown.

# Working with visualization objects

> Read measures, attributes, filters, and identity from IInsight with the insight* accessors, and derive copies with insightSet*.

API reference: [IInsight](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iinsight/index.md) (type-alias), [IInsightDefinition](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iinsightdefinition/index.md) (type-alias), [insightMeasures()](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightmeasures/index.md) (function), [insightFilters()](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightfilters/index.md) (function), [insightSetFilters()](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightsetfilters/index.md) (function)

> **Note:**
>  The term 'insight' is an obsolete expression for 'visualizations' but is still employed within the SDK's components and functions.

A saved visualization is an [`IInsight`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iinsight/index.md). Read it with the accessors below, and derive a changed copy with the setters.

## [Concepts](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/data-model/insights/#concepts)

[`IInsightDefinition`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iinsightdefinition/index.md) holds what the visualization shows: buckets of measures and attributes, filters, sorts, visualization properties, a title, and a `visualizationUrl` naming the visualization type. [`IInsight`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iinsight/index.md) extends it with identity: the object reference, identifier, URI, and audit fields.

You get an [`IInsight`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iinsight/index.md) from `backend.workspace(workspace).insights().getInsight(ref)`, from the `selectInsights` selector in the [`Dashboard`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-ui-dashboard/sdk-ui-dashboard.dashboard/index.md) component, or as the `insight` prop of a custom visualization component registered by a dashboard plugin.

All data sits under `insight.insight`. Don't read that body directly: the accessors validate their input and keep working when the internal layout changes.

## [Read the definition](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/data-model/insights/#read-the-definition)

| Accessor | Returns |
|----------|---------|
| [`insightTitle(insight)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insighttitle/index.md) | `string` |
| [`insightVisualizationUrl(insight)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightvisualizationurl/index.md) | `string`, for example `"local:column"` or `"local:table"` |
| [`insightBuckets(insight, ...ids)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightbuckets/index.md) | [`IBucket[]`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.ibucket/index.md), optionally only the buckets with the given local identifiers |
| [`insightBucket(insight, id)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightbucket/index.md) | `IBucket \| undefined` |
| [`insightMeasures(insight, predicate?)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightmeasures/index.md) | [`IMeasure[]`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.imeasure/index.md) across all buckets |
| [`insightAttributes(insight, predicate?)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightattributes/index.md) | [`IAttribute[]`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iattribute/index.md) across all buckets |
| [`insightFilters(insight)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightfilters/index.md) | [`IFilter[]`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.ifilter/index.md) |
| [`insightSorts(insight)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightsorts/index.md) | [`ISortItem[]`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.isortitem/index.md) |
| [`insightProperties(insight)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightproperties/index.md) | [`VisualizationProperties`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.visualizationproperties/index.md) |
| [`insightTags(insight)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insighttags/index.md) | `string[]` |

Combine them with the measure and attribute accessors:

```ts
import {
    attributeDisplayFormRef,
    insightAttributes,
    insightFilters,
    insightMeasures,
    insightTitle,
    measureIdentifier,
    type IInsight,
} from "@gooddata/sdk-model";

function summarize(insight: IInsight) {
    return {
        title: insightTitle(insight),
        measureIdentifiers: insightMeasures(insight).map(measureIdentifier),
        displayForms: insightAttributes(insight).map(attributeDisplayFormRef),
        filterCount: insightFilters(insight).length,
    };
}
```

To read one bucket, ask for it by local identifier. The identifiers depend on the visualization type. For example, a column chart uses `measures`, `view`, and `stack`.

```ts
import { bucketMeasures, insightBucket, type IInsight } from "@gooddata/sdk-model";

function primaryMeasures(insight: IInsight) {
    const measuresBucket = insightBucket(insight, "measures");

    if (!measuresBucket) {
        return [];
    }

    return bucketMeasures(measuresBucket);
}
```

Tags are the usual way to group saved visualizations. `insightTags` returns an empty array when there are none, so `insightTags(insight).includes("featured")` needs no guard.

## [Read the identity](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/data-model/insights/#read-the-identity)

| Accessor | Returns |
|----------|---------|
| [`insightRef(insight)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightref/index.md) | [`ObjRef`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.objref/index.md) |
| [`insightId(insight)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightid/index.md) | `string` |
| [`insightUri(insight)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insighturi/index.md) | `string` |
| [`insightCreated(insight)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightcreated/index.md) | `string \| undefined` |
| [`insightUpdated(insight)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightupdated/index.md) | `string \| undefined` |

Compare references with `areObjRefsEqual`, not by identifier string. See [Working with object references](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/data-model/object-references/index.md).

## [Derive a modified copy](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/data-model/insights/#derive-a-modified-copy)

The setters return a new object and leave the input unchanged. When you pass an [`IInsight`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iinsight/index.md), you get an [`IInsight`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.iinsight/index.md) back with the identity intact.

| Setter | Replaces |
|--------|----------|
| [`insightSetFilters(insight, filters)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightsetfilters/index.md) | the filters |
| [`insightSetSorts(insight, sorts)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightsetsorts/index.md) | the sorts |
| [`insightSetProperties(insight, properties)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightsetproperties/index.md) | the visualization properties |
| [`insightSetBuckets(insight, buckets)`](https://www.gooddata.ai/docs/gooddata-ui/latest/api-reference/sdk-model/sdk-model.insightsetbuckets/index.md) | the buckets |

The common case is adding filters before execution:

```ts
import { insightFilters, insightSetFilters, type IFilter, type IInsight } from "@gooddata/sdk-model";

function withExtraFilters(insight: IInsight, extraFilters: IFilter[]): IInsight {
    return insightSetFilters(insight, [...insightFilters(insight), ...extraFilters]);
}
```

Execute the copy with `backend.workspace(workspace).execution().forInsight(copy)`; see [ExecuteInsight](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/execute-insight/index.md). Inside a dashboard, `useWidgetFilters` gives you the filters to pass here; see [useWidgetFilters](https://www.gooddata.ai/docs/gooddata-ui/latest/dashboard-plugins/use-widget-filters/index.md).

## [Notes](https://www.gooddata.ai/docs/gooddata-ui/latest/data-layer/data-model/insights/#notes)

- `insightMeasures` and `insightAttributes` accept a predicate to pick items, for example `insightMeasures(insight, isSimpleMeasure)`.
- `insightVisualizationUrl` is the stable way to learn the visualization type. Compare the whole string; do not parse it.
