# tableau Api Tableau Web Data Connector (webdataconnector) - Full Documentation ## @tableau/taco-toolkit - v2.1.0 ### Index ### Modules [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # About Tableau Help 🕐 _1 min read_ ## Addressing Implicit Bias in Technical Language In an effort to align with one of our core company values, equality, we have changed terminology to be more inclusive where possible. Because changing terms in code can break current implementations, we maintain the current terminology in the following places: - Tableau APIs: methods, parameters, and variables - Tableau CLIs: commands and options - Installers, installation directories, and terms in configuration files - Tableau Resource Monitoring Tool (we plan to make changes to non-inclusive terminology in the web interface, error messages, and related documentation soon.) - Third-party systems documentation For more information about our ongoing effort to address implicit bias, see [Salesforce Updates Technical Language in Ongoing Effort to Address Implicit Bias](https://www.salesforce.com/news/stories/salesforce-updates-technical-language-in-ongoing-effort-to-address-implicit-bias) on the Salesforce website. - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [AggType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.AggType.html) # Enumeration AggType The aggregation type for a table column. It can be assigned as metadata for columns of the int and float dataType. ##### Index ### Enumeration Members [Avg](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.AggType.html#Avg) [Count](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.AggType.html#Count) [CountDist](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.AggType.html#CountDist) [Median](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.AggType.html#Median) [Sum](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.AggType.html#Sum) ## Enumeration Members ### Avg[](#Avg) Avg: "avg" ### Count[](#Count) Count: "count" ### CountDist[](#CountDist) CountDist: "count\_dist" ### Median[](#Median) Median: "median" ### Sum[](#Sum) Sum: "sum" ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [Avg](#Avg) - [Count](#Count) - [CountDist](#CountDist) - [Median](#Median) - [Sum](#Sum) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [AjaxResponse](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.AjaxResponse.html) # Interface AjaxResponse #### Type Parameters - #### D = any #### Hierarchy - AjaxResponse ##### Index ### Properties [body](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.AjaxResponse.html#body) [headers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.AjaxResponse.html#headers) [ok](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.AjaxResponse.html#ok) [status](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.AjaxResponse.html#status) [text](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.AjaxResponse.html#text) [type](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.AjaxResponse.html#type) ## Properties ### body[](#body) body: D ### headers[](#headers) headers: Record ### ok[](#ok) ok: boolean ### status[](#status) status: number ### text[](#text) text: string ### type[](#type) type: string ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [body](#body) - [headers](#headers) - [ok](#ok) - [status](#status) - [text](#text) - [type](#type) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) # Module app ##### Index ### References [default](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html#default) ### Enumerations [AggType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.AggType.html) [ColumnRole](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.ColumnRole.html) [ColumnType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.ColumnType.html) [DataType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.DataType.html) [GeographicRole](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html) [NumberFormat](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.NumberFormat.html) [UnitsFormat](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.UnitsFormat.html) ### Classes [Connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html) [Logger](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Logger.html) [OAuthCredentials](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.OAuthCredentials.html) ### Interfaces [AjaxResponse](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.AjaxResponse.html) [ConnectorRequestOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.ConnectorRequestOptions.html) ### Type Aliases [AuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.AuthHeader.html) [AuthTokens](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.AuthTokens.html) [HandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.HandlerInput.html) [SecretsType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.SecretsType.html) ### Functions [getAuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/functions/app.getAuthHeader.html) [getBasicAuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/functions/app.getBasicAuthHeader.html) [getOAuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/functions/app.getOAuthHeader.html) ## References ### default[](#default) Renames and re-exports [Connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html) ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [default](#default) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [AsyncParser](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.AsyncParser.html) # Class AsyncParser`Abstract` An abstract class for the implementation of connector custom parsing that asynchronously parses the results yielded from the Fetcher. For TypeScript, the fetcherResult type can be provided via the type parameter. By default, fetcherResult is typed as `any`. #### Example ```ts export default class MyParser extends AsyncParser { async parse(fetcherResult: Uint8Array, options: ParseOptions): Promise { // ... }} ``` #### Type Parameters - #### FetchResult = any #### Hierarchy - BaseParser - AsyncParser ##### Index ### Constructors [constructor](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.AsyncParser.html#constructor) ### Methods [parse](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.AsyncParser.html#parse) [createContainerBuilder](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.AsyncParser.html#createContainerBuilder) ## Constructors ### constructor[](#constructor) - new AsyncParser(): [AsyncParser](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.AsyncParser.html)[](#constructor.new_AsyncParser) - #### Type Parameters - #### FetchResult = any #### Returns [AsyncParser](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.AsyncParser.html) Inherited from BaseParser.constructor ## Methods ### `Abstract` parse[](#parse) - parse(fetcherResult, options): Promise<[DataContainer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataContainer.html)\>[](#parse.parse-1) - The method to implement the parsing logic for transforming the fetcherResult into a DataContainer. When a custom parser is defined, the connector must implement this method to perform data parsing. #### Parameters - ##### fetcherResult: FetchResult - ##### options: [ParseOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.ParseOptions.html) #### Returns Promise<[DataContainer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataContainer.html)\> ### `Static` createContainerBuilder[](#createContainerBuilder) - createContainerBuilder(dataContainer): [DataContainerBuilder](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataContainerBuilder.html)[](#createContainerBuilder.createContainerBuilder-1) - A static method to create a DataContainerBuilder instance based on the provided dataContainer object. #### Parameters - ##### dataContainer: [DataContainer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataContainer.html) #### Returns [DataContainerBuilder](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataContainerBuilder.html) Inherited from BaseParser.createContainerBuilder ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [constructor](#constructor) - [parse](#parse) - [createContainerBuilder](#createContainerBuilder) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [Auth](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Auth.html) # Class Auth`Abstract` #### Deprecated Will be removed in the later release. #### Hierarchy - Auth ##### Index ### Constructors [constructor](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Auth.html#constructor) ### Methods [authenticate](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Auth.html#authenticate) [run](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Auth.html#run) ## Constructors ### constructor[](#constructor) - new Auth(): [Auth](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Auth.html)[](#constructor.new_Auth) - #### Returns [Auth](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Auth.html) ## Methods ### `Abstract` authenticate[](#authenticate) - authenticate(options): Promise[](#authenticate.authenticate-1) - #### Parameters - ##### options: [AuthenticateOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.AuthenticateOptions.html) #### Returns Promise ### run[](#run) - run(options): Promise[](#run.run-1) - #### Parameters - ##### options: [AuthenticateOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.AuthenticateOptions.html) #### Returns Promise ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [constructor](#constructor) - [authenticate](#authenticate) - [run](#run) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [AuthenticateOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.AuthenticateOptions.html) # Interface AuthenticateOptions #### Hierarchy - AuthenticateOptions ##### Index ### Properties [handlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.AuthenticateOptions.html#handlerInput) [secrets?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.AuthenticateOptions.html#secrets) ## Properties ### handlerInput[](#handlerInput) handlerInput: [HandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.HandlerInput.html) ### `Optional` secrets[](#secrets) secrets?: [SecretsType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.SecretsType.html) ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [handlerInput](#handlerInput) - [secrets](#secrets) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [AuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.AuthHeader.html) # Type alias AuthHeader AuthHeader: {     Authorization?: string; } Represents an authentication header for making authorized HTTP requests. #### Type declaration - ##### `Optional` Authorization?: string #### Example ```ts const authHeader: AuthHeader = { Authorization: 'Bearer ',}// Usage in an HTTP requestconst requestOptions: RequestOptions = { headers: authHeader, // other request options...} ``` ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [AuthTokens](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.AuthTokens.html) # Type alias AuthTokens AuthTokens: {     accessToken: string;     headers: {         \[key: string\]: string;     }; } Represents authentication tokens containing an access token and additional headers. #### Type declaration - ##### accessToken: string - ##### headers: {     \[key: string\]: string; } - ##### \[key: string\]: string #### Example ```ts const authTokens: AuthTokens = { accessToken: 'your_access_token', headers: { 'Custom-Header': 'value', // other headers... },}// Usage in an HTTP requestconst requestOptions: RequestOptions = { headers: { ...authTokens.headers, Authorization: `Bearer ${authTokens.accessToken}` }, // other request options...} ``` ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [BasicHandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html) # Interface BasicHandlerInput The object type sent by the connector app to handlers. The object is used to perform data extraction. #### Type Parameters - #### Data #### Hierarchy - BasicHandlerInput - [FileBasedHandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FileBasedHandlerInput.html) ##### Index ### Properties [auth?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html#auth) [data](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html#data) [fetcher](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html#fetcher) [parser](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html#parser) ## Properties ### `Optional` auth[](#auth) auth?: string File name of connector authenticator ### data[](#data) data: Data Arbitrary data sent to the connector fetcher ### fetcher[](#fetcher) fetcher: string File name of connector fetcher ### parser[](#parser) parser: string File name of connector parser ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [auth](#auth) - [data](#data) - [fetcher](#fetcher) - [parser](#parser) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [ColumnHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.ColumnHeader.html) # Type alias ColumnHeader ColumnHeader: {     aggType?: [AggType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.AggType.html);     alias?: string;     columnRole?: [ColumnRole](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.ColumnRole.html);     columnType?: [ColumnType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.ColumnType.html);     dataType: [DataType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.DataType.html);     description?: string;     filterable?: boolean;     foreignKey?: ColumnReference;     geoRole?: [GeographicRole](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html);     hidden?: boolean;     id: string;     numberFormat?: [NumberFormat](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.NumberFormat.html);     unitsFormat?: [UnitsFormat](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.UnitsFormat.html); } The type for column metadata in a [DataTable](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html). #### Type declaration - ##### `Optional` aggType?: [AggType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.AggType.html) - ##### `Optional` alias?: string - ##### `Optional` columnRole?: [ColumnRole](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.ColumnRole.html) - ##### `Optional` columnType?: [ColumnType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.ColumnType.html) - ##### dataType: [DataType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.DataType.html) - ##### `Optional` description?: string - ##### `Optional` filterable?: boolean - ##### `Optional` foreignKey?: ColumnReference - ##### `Optional` geoRole?: [GeographicRole](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html) - ##### `Optional` hidden?: boolean FYI: this is not in the WDC docs - ##### id: string - ##### `Optional` numberFormat?: [NumberFormat](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.NumberFormat.html) - ##### `Optional` unitsFormat?: [UnitsFormat](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.UnitsFormat.html) ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [ColumnRole](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.ColumnRole.html) # Enumeration ColumnRole The role for a table column. ##### Index ### Enumeration Members [Dimension](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.ColumnRole.html#Dimension) [Measure](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.ColumnRole.html#Measure) ## Enumeration Members ### Dimension[](#Dimension) Dimension: "dimension" ### Measure[](#Measure) Measure: "measure" ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [Dimension](#Dimension) - [Measure](#Measure) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [ColumnType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.ColumnType.html) # Enumeration ColumnType The type for a table column. ##### Index ### Enumeration Members [Continuous](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.ColumnType.html#Continuous) [Discrete](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.ColumnType.html#Discrete) ## Enumeration Members ### Continuous[](#Continuous) Continuous: "continuous" ### Discrete[](#Discrete) Discrete: "discrete" ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [Continuous](#Continuous) - [Discrete](#Discrete) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [Connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html) # Class Connector The Connector class is a facade class used to talk with the eps main server. #### Hierarchy - Connector ##### Index ### Constructors [constructor](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html#constructor) ### Properties [appSnapshot?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html#appSnapshot) [handlerInputs?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html#handlerInputs) [secrets](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html#secrets) ### Accessors [oAuthCredentials](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html#oAuthCredentials) ### Methods [cancel](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html#cancel) [get](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html#get) [post](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html#post) [submit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html#submit) ## Constructors ### constructor[](#constructor) - new Connector(onInitSuccess?, onInitFailure?): [Connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html)[](#constructor.new_Connector) - #### Parameters - ##### onInitSuccess: ((connector) => void) = onInitSuccessDefault - - (connector): void - #### Parameters - ##### connector: [Connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html) #### Returns void - ##### onInitFailure: ((connector, err) => void) = onInitFailureDefault - - (connector, err): void - #### Parameters - ##### connector: [Connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html) - ##### err: Error #### Returns void #### Returns [Connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Connector.html) ## Properties ### `Optional` appSnapshot[](#appSnapshot) appSnapshot?: object ### `Optional` handlerInputs[](#handlerInputs) handlerInputs?: [HandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.HandlerInput.html)\[\] Property to set an array of [HandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.HandlerInput.html) instances to be transmitted to connector handlers from the connector app. Don’t transmit sensitive information through `handlerInputs` because it could be susceptible to logging and internal storage. ### secrets[](#secrets) secrets: undefined | [SecretsType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.SecretsType.html) Property is used to transmit sensitive information to connector handlers from the connector app. In Tableau apps, Secrets are excluded from storage within saved workbooks. Secrets are securely retained in Tableau Server’s keychain. ## Accessors ### oAuthCredentials[](#oAuthCredentials) - get oAuthCredentials(): [OAuthCredentials](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.OAuthCredentials.html) - #### Returns [OAuthCredentials](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.OAuthCredentials.html) ## Methods ### cancel[](#cancel) - cancel(): void[](#cancel.cancel-1) - #### Returns void ### get[](#get) - get(url, requestOptions?): Promise<[AjaxResponse](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.AjaxResponse.html)\>[](#get.get-1) - Send a GET request. By default, it sends the request directly to the endpoint. When requestOptions.bypassCorsPolicy is set, the request will be forwarded to EPS. This can be used when a server has certain CORS policy. When EPS receives the forwarded request, it will validate the connector's permission settings defined in the connector.json. The function also validates the connector's permission settings on the client. #### Parameters - ##### url: string - ##### `Optional` requestOptions: [ConnectorRequestOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.ConnectorRequestOptions.html) #### Returns Promise<[AjaxResponse](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.AjaxResponse.html)\> ### post[](#post) - post(url, body?, requestOptions?): Promise<[AjaxResponse](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.AjaxResponse.html)\>[](#post.post-1) - Send a POST request. By default, it sends the request directly to the endpoint. When requestOptions.bypassCorsPolicy is set, the request will be forwarded to EPS. This can be used when a server has certain CORS policy. When EPS receives the forwarded request, it will validate the connector's permission settings defined in the connector.json. The function also validates the connector's permission settings on the client. #### Parameters - ##### url: string - ##### `Optional` body: object - ##### `Optional` requestOptions: [ConnectorRequestOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.ConnectorRequestOptions.html) #### Returns Promise<[AjaxResponse](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.AjaxResponse.html)\> ### submit[](#submit) - submit(): Promise[](#submit.submit-1) - #### Returns Promise ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [constructor](#constructor) - [appSnapshot](#appSnapshot) - [handlerInputs](#handlerInputs) - [secrets](#secrets) - [oAuthCredentials](#oAuthCredentials) - [cancel](#cancel) - [get](#get) - [post](#post) - [submit](#submit) Generated using [TypeDoc](https://typedoc.org/) **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Connector Boilerplates 🕐 _2 min read_ The Web Data Connector comes with boilerplate connectors that you can use as templates to build your own connector. Also, these boilerplate connectors help you can learn about specific features of the WDC SDK. The boilerplates are built using the TACO Toolkit. - [Basic authentication connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/docs/wdc_create_basic_auth_connector.html) This connector shows you how to create your own connector authorized by username and password. Use cases are basic authentication, Excel, built-in Excel parser. - [Cloud file connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/docs/wdc_create_cloud_file_connector.html) This connector ingests large file-based comma-separated value (CSV) data with loadCsvData Fetch API and the built-in TACO file parser. Use cases are React, CSV, built-in CSV parser, large file ingestion, and paginated ingestion. - [Custom parse connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/docs/wdc_create_custom_parse_connector.html) This connector ingests the fetched binary data using parse utilities for custom parsing. Use cases are custom parsing, Excel, CSV, ExcelUtils, CsvUtils, and multi-table ingestion. - [Earthquake data connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/index.html) This is the default connector when you created [your first connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/index.html). This connector connects to the United States Geological Survey (USGS) Earthquake feed and gets data about earthquakes in the last week. Use cases are JSON, custom parsing, and TypeScript. We recommend using this as your first connector for learning web data connector structure and workflow. - [Earthquake data connector with JavaScript](https://help.tableau.com/v0.0/api/webdataconnector/en-us/docs/wdc_create_earthquake_data_js.html) This connector connects to the United States Geological Survey (USGS) Earthquake feed and gets data about earthquakes in the last week. It contains simple JavaScript and HTML. Use cases are JSON, custom parsing, and JavaScript. - [OAuth connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/docs/wdc_create_oauth_connector.html) This connector demonstrates how to use the locale property of the Tableau object to localize content. Use cases are React, OAuth, JSON, and paginated ingestion. For more information about how Tableau handles data connection with OAuth, see [OAuth Connections](https://help.tableau.com/current/server/en-us/protected_auth.htm) in the Tableau Server help. - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [ConnectorRequestOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.ConnectorRequestOptions.html) # Interface ConnectorRequestOptions #### Hierarchy - ConnectorRequestOptions ##### Index ### Properties [bypassCorsPolicy?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.ConnectorRequestOptions.html#bypassCorsPolicy) [headers?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/app.ConnectorRequestOptions.html#headers) ## Properties ### `Optional` bypassCorsPolicy[](#bypassCorsPolicy) bypassCorsPolicy?: boolean Set to `true` if the requested server doesn't allow CORS requests from browser. In this case, the request will go through EPS server which acts as a proxy between user's client and the requested URL. ### `Optional` headers[](#headers) headers?: Record ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [bypassCorsPolicy](#bypassCorsPolicy) - [headers](#headers) Generated using [TypeDoc](https://typedoc.org/) **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Considerations for Building Your Connector 🕐 _7 min read_ This topic tries to clarify some design and implementation ideas that have traditionally been part of Web Data Connector. ## Cross-origin resource sharing The JavaScript code in your web data connector makes requests to a server that’s on a different domain than your web data connector’s HTML page. That is, the code makes requests that represent cross-origin resource sharing (CORS). As a security measure, most browsers restrict CORS requests made from JavaScript code. This restriction can result in errors when the web data connector runs. For example, if the code in your connector makes requests to a server that doesn’t allow CORS requests, you might see an error like the following in your browser console: ``` XMLHttpRequest cannot load URL. No 'Access-Control-Allow-Origin' header is present on the requested resource. ``` If you find that the domain your connector’s requested domain has CORS policy restrictions, you can use the functionality in the [TACO Toolkit SDK](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) to bypass the CORS policy and get the data from another API: ``` connector.get(url, {bypassCorsPolicy:true}) ``` ## Parsing data - The parser file (located in the `handlers/` directory) extends the proper parser class. The TACO Toolkit provides two base parser classes, Parser and AsyncParser. The difference between the two classes is that the signatures of the `.parse()` function from the classes are sync and async accordingly. So if the custom parser needs an async operation, such as loading external resources for parsing, you should extend the AsyncParser. Otherwise, we recommend that you use the Parser class. - Always use `ContainerBuilder` to mutate dataContainer in `parser. AsyncParser.createContainerBuilder(dataContainer)`. This guarantees that the `dataContainer` object is always in a proper shape. - The parser file also returns the `dataContainer` from the `.parse()` function. For performance purposes, a `dataContainer` passed to the `.parse()` function is a mutable object. However, it doesn’t mean directly mutating the `dataContainer` object takes any effect in the connector runtime engine. ## Authentication Many connectors require authentication to connect to a data source. For these connectors, the TACO Toolkit provides boilerplate files that handle different types of authentication. The TACO Toolkit supports three types of authentication: - Basic - Custom - OAuth ### Basic Basic authentication is a method that requires a username and password when making a request. If you create a basic authentication connector, Tableau displays a standard username and password dialog. To create a basic authentication connector, see [Create a Basic Authentication Connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/docs/wdc_create_basic_auth_connector.html). ### Custom Custom authentication allows you to set up an authentication process to support API keys or tokens, including authenticating the user through a third-party system. ### OAuth OAuth is an authentication protocol that allows your web data connector to request specific resources from a resource provider on behalf of a specific resource owner. This is a more secure and usable alternative to a connector that asks the user directly for their username and password. To use OAuth, your connector must be registered with the OAuth resource provider. The provider assigns a _client ID_ to identify the connector and a _client secret_ that is known only by the connector and the OAuth provider and is used to authorize the connector to make requests on behalf of the user. When your connector contacts the OAuth provider, the connector passes the client ID to identify itself. The exact process for registering your connector differs for each provider, and is typically explained in the provider’s documentation for how to use their API. #### Benefits of OAuth Using OAuth-based connections provides the following benefits: - **Security**: Your database credentials are never known to or stored in Tableau Server, and the access token can be used only by Tableau on behalf of users. - **Convenience**: Instead of having to embed your data source ID and password in multiple places, you can use the token provided for a particular data provider for all published workbooks and data sources that access that data provider. To create an OAuth connector, see [Create an OAuth Connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/docs/wdc_create_oauth_connector.html). #### Configuring for OAuth Each OAuth config attribute is represented by an element in the XML, the element name is the attribute name and the content is the attribute value. | Name | Type | Meaning | Required? | Notes | | --- | --- | --- | --- | --- | | dbclass | String | The identifier for your oauthConfig | Yes | The dbclass must be same with as the `class` attribute in manifest.xml | | clientIdDesktop | String | Client ID you registered for Tableau Desktop | No | This isn’t considered a secret and will be stored in plain text | | clientSecretDesktop | String | Client Secret you registered for Tableau Desktop | No | This isn’t considered a secret and will be stored in plain text | | redirectUrisDesktop | String\[\] | Redirect Urls for Desktop | No | Only required when `OAUTH_CAP_FIXED_PORT_IN_CALLBACK_URL` is set to true. The host for redirectUrisDesktop must be a valid loopback address | | authUri | String | Authorization endpoint URI | Yes |   | | tokenUri | String | Token endpoint URI | Yes |   | | userInfoUri | String | User Info UrI | No |   | | instanceUrlValidationRegex | String | Use to validate against your OAuth instance Url. | No |   | | scopes | String\[\] | scopes | Yes |   | | capabilities | Map | This defines how OAuth flow behaves differently according to the capabilities set. | No |   | | accessTokenResponseMaps | Map | Key value pair that maps an initial token request response attribute to Tableau recognized attribute | Yes |   | | refreshTokenResponseMaps | Map | Key value pair that maps a refresh token request response attribute to Tableau recognized attribute | No | If not defined will use accessTokenResponseMaps by default | Note: The keys in accessTokenResponseMaps and refreshTokenResponseMaps are Tableau preferred field names and are defined in the followed table. The values are what your OAuth provider returns in the raw response | Name of the key | Required for accessTokenResponseMaps | Required for refreshTokenResponseMaps | Notes | | --- | --- | --- | --- | | ACCESSTOKEN | Yes | Yes | Used by Tableau to connect to your data. | | REFRESHTOKEN | Yes | No | Used by Tableau to get a new ACCESSTOKEN when the old one expired. | | username | Yes | No | Used by Tableau to identify the token. | | access-token-issue-time | No | No | Used to note when the token is issued, will default to the time when the token is sent back to Tableau if not set. | | access-token-expires-in | No | No | Use to note the validation time of your ACCESSTOKEN, which will default to 3600 seconds if not set. | | id-token | No | No | If you have openid as your scope this field is returned and can be used to retrieve userinfo. Use together with OAUTH\_CAP\_SUPPORTS\_GET\_USERINFO\_FROM\_ID\_TOKEN | | \[your own field\] | No | No | It’s usually not needed to define your own field, and this field won’t be able to participate in any OAuth flow. | #### OAuth configuration capabilities This set of OAuth configuration capabilities is not shared with the regular connector capabilities. | Capability Name | Description | Default | Recommendation | | --- | --- | --- | --- | | OAUTH\_CAP\_SUPPORTS\_CUSTOM\_DOMAIN | Whether your OAuth provider supports a custom domain. i.e. OAuth endpoint host isn’t fixed. | false | \- | | OAUTH\_CAP\_REQUIRE\_PKCE | Whether your OAuth provider supports PKCE, more details: https://oauth.net/2/pkce/ | false | true | | OAUTH\_CAP\_PKCE\_REQUIRES\_CODE\_CHALLENGE\_METHOD | Whether your OAuth provider PKCE requires code\_challenging\_method passed in. If set to true, we’re using S256 by default. | false | true | | OAUTH\_CAP\_SUPPORTS\_STATE | Used to protect against CSRF attacks, more details: https://auth0.com/docs/protocols/state-parameters | false | true | | OAUTH\_CAP\_GET\_USERNAME\_USES\_POST\_REQUEST | Only use if you define a USERINFO\_URI in the oauthConfig file to retrieve the userinfo in a separate request | false | \- | | OAUTH\_CAP\_CLIENT\_SECRET\_IN\_URL\_QUERY\_PARAM | Use this if Client secrets are expected in the query parameter instead of the request header. | false | \- | | OAUTH\_CAP\_FIXED\_PORT\_IN\_CALLBACK\_URL | Use this when your OAuth provider native app(Tableau Desktop) OAuth clients only support a fixed callback url | false | \- | | OAUTH\_CAP\_SUPPORTS\_HTTP\_SCHEME\_LOOPBACK\_REDIRECT\_URLS | Use this when your OAuth provider native app(Tableau Desktop) OAuth clients support Loopback callback url. E.g. https://developers.google.com/identity/protocols/oauth2/native-app | false | \- | | OAUTH\_CAP\_REQUIRES\_PROMPT\_CONSENT | Add prompt=consent to the request. | false | \- | | OAUTH\_CAP\_REQUIRES\_PROMPT\_SELECT\_ACCOUNT | Add propmt=select\_account to the request. More details: https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-auth-code-flow | false | \- | | OAUTH\_CAP\_SUPPORTS\_GET\_USERINFO\_FROM\_ID\_TOKEN | Used when your OAuth response contains a JWT style ID\_TOKEN that can be parsed out to get an actual username. For example, https://docs.microsoft.com/en-us/azure/active-directory/develop/id-tokens | false | \- | ## Multiple tables Web Data Connector 3.0 supports multiple table connectors by default. **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Create a Basic Authentication Connector 🕐 _5 min read_ The basic authentication boilerplate is a connector that ingests Excel data and uses the built-in TACO Excel file parser from a basic authentication endpoint. ## Use cases - Basic authentication - Custom authentication - Excel - Built-in Excel parser ## Instructions To create your basic authentication connector, we recommend that you first create a sample basic authentication connector and edit the generated files. It’s easier to get all the files and directory structure your connector needs by just using an existing example. To create your basic authentication connector, do the following steps. ### Step 1: Create a boilerplate basic authentication connector 1. Enter the following command to create the connector: ``` taco create my-basic-auth-connector --boilerplate basic-auth ``` This creates a directory with the earthquake data boilerplate code, which is included with the toolkit. 2. Change directories to the `my-basic-auth-connector` directory. ``` cd my-basic-auth-connector ``` 3. Build the connector by entering the following command: ``` taco build ``` This command clears any previous or existing build caches, then installs the dependencies, then builds the frontend code and the backend code (handlers), then copies the connector.json file (the configuration file). ### Step 2: Configure your connector’s properties In your new basic authentication connector directory, find and open the `connector.json` file. ``` { "name": "my-basic-auth-connector", "version": "1.0.0", "tableau-version": { "min": "2022.3" }, "vendor": { "name": "vendor-name", "support-link": "https://vendor-name.com", "email": "support@vendor-name.com" }, "permission": { "api": { "https://*.usgs.gov/": [ "GET", "POST", "HEAD" ] } }, "auth": { "type": "custom" }, "window": { "height": 800, "width": 600 } } ``` Make the following changes: 1. Change the general properties. | Name | Value | | --- | --- | | name | Your connector’s directory name | | displayName | Your connector’s name. This is the name that appears in the Tableau connectors area. | | version | Your connector’s version | | min | The earliest Tableau version your connector supports | 2. Change the company properties. | Name | Value | | --- | --- | | vendor.name | Your company name | | vendor.support-link | Your company’s URL | | vendor.email | Your company’s email | 3. Change the permissions. | Name | Value | | --- | --- | | permission.api | The URI for the API that the connector is allowed to access, along with the methods (POST, GET, PUT, PATCH, DELETE) that the connector is allowed to use. | 4. Verify the authentication value. | Name | Value | | --- | --- | | auth.type | Set to `custom` | `custom` covers basic authentication (username and password) and custom authentication (API keys or tokens). For more information about authentication, see the Authentication section in the [Considerations for Building Your Connector](/v0.0/api/webdataconnector/en-us/docs/wdc_dev_considerations.html) topic. 5. Change the HTML pane size. | Name | Value | | --- | --- | | window.height | The height of the connector HTML pane | | window.width | The width of the connector HTML pane | ### Step 3: Edit the user interface When you open a web data connector in Tableau, the connector displays an HTML page that links to your JavaScript code and to your connector’s handlers. Optionally, this page can also display a user interface for your users to select the data that they want to download. To create a user interface (UI) for your connector, open the `/app/index.html` file and make any edits for your connector. ``` Basic Auth Sample Connector

Basic Auth Sample Connector
``` Some notes about what the code is doing: - The `meta` tag prevents your browser from caching the page. - The `index.css` file is used to simplify styling and formatting. - The `index.ts` file is the code for your connector. - The `input type="text"` is the form field for the username. - The `input type="password"` is the form field for the password. ### Step 4: Edit the connector object Now that you’ve created a user interface, it’s time to edit the JavaScript code for the connector’s button. The code is in the `/app/index.js` file. - The connector object is used to submit data from the connector UI to connector handlers. ``` const connector = new Connector(() => { connectorInitialized = true enableButtonWhenReady() }) ``` - The following code shows how a connector sets variables (for example, secrets, handlerInputs) for the connector object before submitting. ``` function submit() { const username = document.querySelector('#username')?.value const password = document.querySelector('#password')?.value if (!username || !password) { return } connector.secrets = { username, password } connector.handlerInputs = [ { fetcher: 'DataFetcher', parser: 'taco:excel-file-parser', data: {}, name: 'unique-workbook-name', }, ] connector.submit() } ``` For more information about the Connector object, see [Class Connector](https://help.vnext.tabint.net/current/api/webdataconnector/en-us/reference/classes/app.Connector.html) in the SDK documentation. ### Step 5: Update the fetcher file If your data is complex and needs preprocessing, use the TACO Toolkit library to prepare your data. The following is the default code in the `handlers/DataFetcher.js` file that gets the data: ``` import { Fetcher, FetchUtils, FetchOptions, getBasicAuthHeader } from '@tableau/taco-toolkit/handlers' export default class DataFetcher extends Fetcher { async *fetch({ secrets }: FetchOptions) { const { username, password } = secrets const headers = getBasicAuthHeader(username, password) // PLACEHOLDER: the url is NOT real endpoint. // Replace the url with actual endpoint that supports basic auth for corresponding file type. // Note: the permission setting in connector.json also needs to be updated accordingly. const url = 'https://www.example.com/api/user' yield await FetchUtils.loadExcelData(url, { headers }) } } ``` For information about `FetchUtils.loadExcelData`, see [loadExcelData](https://) ### Step 6: Build your connector Enter these commands to build, pack, and run your new connector: ``` taco build ``` ``` taco pack ``` ``` taco run Desktop ``` **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Create a Cloud File Connector 🕐 _4 min read_ The cloud file boilerplate is a connector that ingests large file-based comma-separated values (CSV) data with loadCsvData Fetch API and built-in taco file parser. ## Use cases - React - CSV - Built-in CSV parser - Large file ingestion - Paginated ingestion ## Instructions To create your connector, we recommend that you first create a sample cloud file connector from the boilerplate and edit the generated files. It’s easier to get all the files and directory structure your connector needs by just using an existing example. To create your cloud file connector, do the following steps. ## Step 1: Create a boilerplate React connector 1. Enter the following command to create the connector: ``` taco create my-cloud-file-connector --boilerplate cloud-file ``` This creates a directory with the cloud file data boilerplate code, which is included with the toolkit. 2. Change directories to the `my-cloud-file-connector` directory. ``` cd my-cloud-file-connector ``` 3. Build the connector by entering the following command: ``` taco build ``` This command clears any previous or existing build caches, then installs the dependencies, then builds the frontend code and the backend code (handlers), then copies the connector.json file (the configuration file). ## Step 2: Configure your connector’s properties In your new cloud file connector directory, find and open the `connector.json` file. ``` { "name": "my-cloud-file-connector", "displayName": "Cloud File Sample Connector", "version": "1.0.0", "tableau-version": { "min": "2023.3" }, "vendor": { "name": "vendor-name", "support-link": "https://vendor-name.com", "email": "support@vendor-name.com" }, "permission": { "api": { "https://*.usgs.gov/": [ "GET", "POST" ] } }, "auth": { "type": "none" }, "window": { "height": 800, "width": 600 } } ``` Make the following changes: 1. Change the general properties. | Name | Value | | --- | --- | | name | Your connector’s directory name | | displayName | Your connector’s name. This is the name that appears in the Tableau connectors area. | | version | Your connector’s version | | min | The earliest Tableau version your connector supports | 2. Change the company properties. | Name | Value | | --- | --- | | vendor.name | Your company name | | vendor.support-link | Your company’s URL | | vendor.email | Your company’s email | 3. Change the permissions. | Name | Value | | --- | --- | | permission.api | The URI for the API that the connector is allowed to access, along with the methods (POST, GET, PUT, PATCH, DELETE) that the connector is allowed to use. | 4. Change the authentication type. | Name | Value | | --- | --- | | auth.type | Accepted values are `custom`, `oauth`, and `none`. | For more information about authentication, see the Authentication section in the [Considerations for Building Your Connector](/v0.0/api/webdataconnector/en-us/docs/wdc_dev_considerations.html) topic. 5. Change the HTML pane size. | Name | Value | | --- | --- | | window.height | The height of the connector HTML pane | | window.width | The width of the connector HTML pane | ## Step 3: Edit the user interface When you open a web data connector in Tableau, the connector displays an HTML page that links to your code and to your connector’s handlers. Optionally, this page can also display a user interface (UI) for your users to select the data that they want to download. The `/app/components/ConnectorView.tsx` file is the main component for the connector UI. You can modify or replace this file based on your connector UI requirements. ## Step 4: Edit the connector object The `/app/components/useConnector.ts` file contains a custom React [hook](https://react.dev/learn/reusing-logic-with-custom-hooks) that abstracts common connector object operations. The hook creates a connector object. A component can: - Track the connector object state (for example, `isInitializing`) - Directly invoke the functions returned from the hook to interact with connector object (for example, `handleSubmit`) The following is the code in `userConnector.ts` file for the connector creation. ``` const [connector] = useState( () => new Connector( (_: Connector) => { Logger.info('Connector initialized.') setConnectorState({ ...connectorState, isInitializing: false }) }, (_: Connector, error: Error) => { Logger.error(`Connector Initialized Error: ${error.message}`) setConnectorState({ ...connectorState, errorMessage: error.message, isInitializing: false }) } ) ) ``` ## Step 5: Update the fetcher file If your data is complex and needs preprocessing, use the TACO Toolkit library to prepare your data. The following is the default code that the `/handlers/LoadCsvDataFetcher.ts` files uses to get the data: ``` import { Fetcher, FetchUtils } from '@tableau/taco-toolkit/handlers' export default class LoadCsvDataFetcher extends Fetcher { async *fetch() { const csvDataUrls = [ 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/1.0_month.csv', 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_month.csv', ] for (const url of csvDataUrls) { await FetchUtils.loadCsvData(url, { trimColumnHeader: true, }) } yield } } ``` ## Step 6: Build your connector Enter these commands to build, pack, and run your new connector: ``` taco build ``` ``` taco pack ``` ``` taco run Desktop ``` **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Create a Custom Parse Connector 🕐 _5 min read_ The custom parse connector ingests the fetched binary data using parse utils for custom parsing. ## Use cases - Custom parsing - Excel - CSV - ExcelUtils - CsvUtils - Multi-table ingestion ## Instructions To create your custom parse connector, we recommend that you first create a sample custom parse connector and edit the generated files. It’s easier to get all the files and directory structure your connector needs by just using an existing example. **Notes**: - Custom parsing currently doesn’t support datasets larger than 100 MB. - If your data is complex and needs preprocessing, use the TACO Toolkit library to prepare your data. To create your custom parse connector, do the following steps. ### Step 1: Create a boilerplate custom parse connector 1. Enter the following command to create the connector: ``` taco create my-custom-parse-connector --boilerplate custom-parse ``` This creates a directory with the custom parse boilerplate code, which is included with the toolkit. 2. Change directories to the `my-custom-parse-connector` directory. ``` cd my-custom-parse-connector ``` 3. Build the connector by entering the following command: ``` taco build ``` This command clears any earlier or existing build caches. Then the command installs the dependencies and builds both the front-end code and the back-end code (handlers). Finally, the command copies the `connector.json` file (the configuration file) to your directory. ### Step 2: Configure your connector’s properties In your new custom parse connector directory, find and open the `connector.json` file. ``` { "name": "my-custom-parse-connector", "version": "1.0.0", "tableau-version": { "min": "2023.3" }, "vendor": { "name": "vendor-name", "support-link": "https://vendor-name.com", "email": "support@vendor-name.com" }, "permission": { "api": { "https://*.example.com/": [ "GET", "POST" ] } }, "auth": { "type": "none" }, "window": { "height": 800, "width": 600 } } ``` Make the following changes: 1. Change the general properties. | Name | Value | | --- | --- | | name | Your connector’s name | | version | Your connector’s version | | min | The earliest Tableau version your connector supports | 2. Change the company properties. | Name | Value | | --- | --- | | vendor.name | Your company name | | vendor.support-link | Your company’s URL | | vendor.email | Your company’s email | 3. Change the permissions. | Name | Value | | --- | --- | | permission.api | The URI for the API that the connector is allowed to access, along with the methods (POST, GET, PUT, PATCH, DELETE) that the connector is allowed to use. | 4. Verify the authentication value | Name | Value | | --- | --- | | auth.type | Set to `none` | For more information about authentication, see the Authentication section in the [Considerations for Building Your Connector](/v0.0/api/webdataconnector/en-us/docs/wdc_dev_considerations.html) topic. 5. Change the HTML pane size. | Name | Value | | --- | --- | | window.height | The height of the connector HTML pane | | window.width | The width of the connector HTML pane | ### Step 3: Edit the user interface When you open a web data connector in Tableau, the connector displays an HTML page that links to your code and to your connector’s handlers. Optionally, this page can also display a user interface (UI) for your users to select the data that they want to download. The `/app/components/ConnectorView.tsx` file is the main component for the connector UI. You can modify or replace this file based on your connector UI requirements. ### Step 4: Edit the connector object The `/app/components/useConnector.ts` file contains a custom React [hook](https://react.dev/learn/reusing-logic-with-custom-hooks) that abstracts common connector object operations. The hook creates a connector object. A component can: - Track the connector object state (for example, `isInitializing`) - Directly invoke the functions returned from the hook to interact with connector object (for example, `handleSubmit`) The following is the code in `userConnector.ts` file for the connector creation. ``` const [connector] = useState( () => new Connector( (_: Connector) => { Logger.info('Connector initialized.') setConnectorState({ ...connectorState, isInitializing: false }) }, (_: Connector, error: Error) => { Logger.error(`Connector Initialized Error: ${error.message}`) setConnectorState({ ...connectorState, errorMessage: error.message, isInitializing: false }) } ) ) ``` ### Step 5: Update the fetcher file Replace the example URL(s) in the `handlers/DataFetcher.ts` file to reflect the URL(s) where your data is stored. ``` urls: Record = { csv: 'https://www.example.com/user.csv', excel: 'https://www.example.com/user.xslx', } as const ``` ### Step 6: Configure how the data is presented Now you must define how you want to map the data to one or more or tables. This mapping of data is done in the schema. To decide how to map your data, look at your data source. When you’re done looking at the summary of the JSON data source, make the necessary edits to structure the returned data. The custom parse connector has two default parsers. The `handlers/CsvDataParser.ts` file: ``` import { CsvUtils, DataContainer, DataType, ParseOptions, AsyncParser } from '@tableau/taco-toolkit/handlers' export default class CsvDataParser extends AsyncParser { async parse(fetcherResult: Uint8Array, { dataContainer }: ParseOptions): Promise { const tableName = 'csv-data-table' const containerBuilder = AsyncParser.createContainerBuilder(dataContainer) const { tableBuilder } = containerBuilder.getTable(tableName) // fetcherResult contains the CSV content yielded from Fetcher const { headers, rows } = await CsvUtils.parse(fetcherResult, { hasHeader: true }) if (!headers) { throw new Error('The parsing result does not include the expected headers.') } tableBuilder.addColumnHeaders(headers.map((id: string) => ({ id, dataType: DataType.String }))) const dataRows = await CsvUtils.createDataRows(rows, headers) tableBuilder.addRows(dataRows) return containerBuilder.getDataContainer() } } ``` The `handlers/ExcelDataParser.ts` file: ``` import { ExcelUtils, DataContainer, ParseOptions, AsyncParser } from '@tableau/taco-toolkit/handlers' export default class ExcelDataParser extends AsyncParser { async parse(fetcherResult: Uint8Array, { dataContainer }: ParseOptions): Promise { // fetcherResult contains the Excel content yielded from Fetcher const tables = await ExcelUtils.parse(fetcherResult) const containerBuilder = AsyncParser.createContainerBuilder(dataContainer) containerBuilder.appendTables(tables) return containerBuilder.getDataContainer() } } ``` ### Step 7: Build your connector Enter these commands to build, pack, and run your new connector: ``` taco build ``` ``` taco pack ``` ``` taco run Desktop ``` **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Create an Earthquake Data Connector 🕐 _4 min read_ The earthquake data JavaScript boilerplate is a connector connecting to earthquake data and contains simple JavaScript and HTML. ## Use cases - JSON - Custom parsing - TypeScript - Good first connector ## Instructions To create your connector, we recommend that you first create a sample earthquake data connector and edit the generated files. It’s easier to get all the files and directory structure your connector needs by just using an existing example. To create your earthquake data connector, do the following steps. ### Step 1: Create a boilerplate earthquake data connector 1. Enter the following command to create the connector: ``` taco create my-earthquake-data-connector --boilerplate earthquake-data ``` This creates a directory with the earthquake data boilerplate code, which is included with the toolkit. 2. Change directories to the `my-earthquake-data-connector` directory. ``` cd my-earthquake-data-connector ``` 3. Build the connector by entering the following command: ``` taco build ``` This command clears any previous or existing build caches, then installs the dependencies, then builds the frontend code and the backend code (handlers), then copies the connector.json file (the configuration file). ### Step 2: Configure your connector’s properties In your new earthquake data connector directory, find and open the `connector.json` file. ``` { "name": "my-earthquake-data-connector", "displayName": "Earthquake Data Connector", "version": "1.0.0", "tableau-version": { "min": "2023.3" }, "vendor": { "name": "vendor-name", "support-link": "https://vendor-name.com", "email": "support@vendor-name.com" }, "permission": { "api": { "https://*.usgs.gov/": [ "GET", "POST" ] } }, "auth": { "type": "none" }, "window": { "height": 800, "width": 600 } } ``` Make the following changes: 1. Change the general properties. | Name | Value | | --- | --- | | name | Your connector’s directory name | | displayName | Your connector’s name. This is the name that appears in the Tableau connectors area. | | version | Your connector’s version | | min | The earliest Tableau version your connector supports | 2. Change the company properties. | Name | Value | | --- | --- | | vendor.name | Your company name | | vendor.support-link | Your company’s URL | | vendor.email | Your company’s email | 3. Change the permissions. | Name | Value | | --- | --- | | permission.api | The URI for the API that the connector is allowed to access, along with the methods (POST, GET, PUT, PATCH, DELETE) that the connector is allowed to use. | 4. Verify the authentication type. | Name | Value | | --- | --- | | auth.type | Enter `none`. | For more information about authentication, see the Authentication section in the [Considerations for Building Your Connector](/v0.0/api/webdataconnector/en-us/docs/wdc_dev_considerations.html) topic. 5. Change the HTML pane size. | Name | Value | | --- | --- | | window.height | The height of the connector HTML pane | | window.width | The width of the connector HTML pane | ### Step 3: Edit the user interface When you open a web data connector in Tableau, the connector displays an HTML page that links to your JavaScript code and to your connector’s handlers. Optionally, this page can also display a user interface for your users to select the data that they want to download. To create a user interface for your connector, open the `/app/index.html` file. ``` USGS Earthquake Feed
``` Let’s run through what the code is doing. Skipping over the standard markup for an HTML page, notice the following between the `head` tags: - The `meta` tag prevents your browser from caching the page. - The `index.css` file is used to simplify styling and formatting. - The `index.ts` file is the code for your connector. ### Step 4: Edit the connector object Now that you’ve created a user interface, it’s time to edit the TypeScript code for the connector’s button. First, open the `/app/index.ts` file. ``` function submit() { connector.handlerInputs = [ { fetcher: 'MyFetcher', parser: 'MyParser', data: { url: 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_week.geojson', }, }, ] connector.submit() } ``` ### Step 5: Update the fetcher file If your data is complex and needs preprocessing, use the TACO Toolkit library to prepare your data. The following is the default code that the `/handlers/MyFetcher.ts` files uses to get the data: ``` import { Fetcher, FetchUtils, FetchOptions } from '@tableau/taco-toolkit/handlers' export default class MyFetcher extends Fetcher { async *fetch({ handlerInput }: FetchOptions) { yield await FetchUtils.fetchJson(handlerInput.data.url) } } ``` ### Step 6: Configure how the data is presented Now you must define how you want to map the data to one or more or tables. This mapping of data is done in the schema. To decide how to map your data, look at your data source. When you’re done looking at the summary of the JSON data source, make the necessary edits in the `/handlers/MyParser.ts` file to structure the returned data. ``` import { DataContainer, DataType, log, ParseOptions, Parser } from '@tableau/taco-toolkit/handlers' interface FeatureRow { id: string properties: { mag: number title: string } geometry: { type: string coordinates: [number, number, number] } } interface FetcherResult { features: FeatureRow[] } export default class MyParser extends Parser { parse(fetcherResult: FetcherResult, { dataContainer }: ParseOptions): DataContainer { const tableName = 'My Sample Data' log(`parsing started for '${tableName}'`) const containerBuilder = Parser.createContainerBuilder(dataContainer) const { isNew, tableBuilder } = containerBuilder.getTable(tableName) if (isNew) { tableBuilder.setId('mySampleData') tableBuilder.addColumnHeaders([ { id: 'id', dataType: DataType.String, }, { id: 'mag', alias: 'magnitude', dataType: DataType.Float, }, { id: 'title', alias: 'title', dataType: DataType.String, }, { id: 'location', dataType: DataType.Geometry, }, ]) } tableBuilder.addRows( fetcherResult.features.map((row) => { return { id: row.id, mag: row.properties.mag, title: row.properties.title, location: row.geometry } }) ) return containerBuilder.getDataContainer() } } ``` Some notes: - You don’t need to write a custom parser for CSV data or for Excel data. The TACO Toolkit contains these parsers. For more information, see [Class CsvUtils](https://help.tableau.com/current/api/webdataconnector/en-us/reference/classes/handlers.CsvUtils.html) and [Class ExcelUtils](https://help.tableau.com/current/api/webdataconnector/en-us/reference/classes/handlers.ExcelUtils.html) in the SDK reference documentation. ### Step 7: Build your connector Enter these commands to build, pack, and run your new connector: ``` taco build ``` ``` taco pack ``` ``` taco run Desktop ``` **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Create an Earthquake Data JavaScript Connector 🕐 _4 min read_ The earthquake data JavaScript (JS) boilerplate connector is a connector connecting to earthquake data and contains simple JavaScript and HTML. ## Use cases - JSON - Custom parsing - JavaScript ## Instructions To create your connector, we recommend that you first create a sample earthquake data connector and edit the generated files. It’s easier to get all the files and directory structure your connector needs by just using an existing example. **Note**: We recommend that you use TypeScript, as shown in the [Earthquake Data Connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/docs/wdc_create_earthquake_data_connector.html). However the Taco Toolkit also supports JavaScript. To create your earthquake data connector, do the following steps. ### Step 1: Create a boilerplate earthquake data connector 1. Enter the following command to create the connector: ``` taco create my-eq-data-js-connector --boilerplate earthquake-data-js ``` This creates a directory with the earthquake data boilerplate code, which is included with the toolkit. 2. Change directories to the `my-eq-data-js-connector` directory. ``` cd my-eq-data-js-connector ``` 3. Build the connector by entering the following command: ``` taco build ``` This command clears any previous or existing build caches, then installs the dependencies, then builds the frontend code and the backend code (handlers), then copies the connector.json file (the configuration file). ### Step 2: Configure your connector’s properties In your new earthquake data connector directory, find and open the `connector.json` file. ``` { "name": "my-eq-data-js-connector", "version": "1.0.0", "tableau-version": { "min": "2023.3" }, "vendor": { "name": "vendor-name", "support-link": "https://vendor-name.com", "email": "support@vendor-name.com" }, "permission": { "api": { "https://*.usgs.gov/": [ "GET", "POST", "HEAD" ] } }, "auth": { "type": "none" }, "window": { "height": 800, "width": 600 } } ``` Make the following changes: 1. Change the general properties. | Name | Value | | --- | --- | | name | Your connector’s directory name | | version | Your connector’s version | | min | The earliest Tableau version your connector supports | 2. Change the company properties. | Name | Value | | --- | --- | | vendor.name | Your company name | | vendor.support-link | Your company’s URL | | vendor.email | Your company’s email | 3. Change the permissions. | Name | Value | | --- | --- | | permission.api | The URI for the API that the connector is allowed to access, along with the methods (POST, GET, PUT, PATCH, DELETE) that the connector is allowed to use. | 4. Verify the authentication type. | Name | Value | | --- | --- | | auth.type | Enter `none` | For more information about authentication, see the Authentication section in the [Considerations for Building Your Connector](/v0.0/api/webdataconnector/en-us/docs/wdc_dev_considerations.html) topic. 5. Change the HTML pane size. | Name | Value | | --- | --- | | window.height | The height of the connector HTML pane | | window.width | The width of the connector HTML pane | ### Step 3: Create the user interface When you open a web data connector in Tableau, the connector displays an HTML page that links to your JavaScript code and to your connector’s handlers. Optionally, this page can also display a user interface for your users to select the data that they want to download. To create a user interface for your connector, open the `/app/index.html` file. ``` USGS Earthquake Feed
``` Let’s run through what the code is doing. Skipping over the standard markup for an HTML page, notice the following between the `head` tags: - The `meta` tag prevents your browser from caching the page. - The `index.css` file is used to simplify styling and formatting. - The `index.js` file is the code for your connector. ### Step 4: Edit the connector object Now that you’ve created a user interface, it’s time to edit the JavaScript code for the connector’s button. First, open the `/app/index.js` file. ``` function submit() { connector.handlerInputs = [ { fetcher: 'MyFetcher', parser: 'MyParser', data: { url: 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_week.geojson', }, }, ] connector.submit() } ``` ### Step 5: Update the fetcher file If your data is complex and needs preprocessing, use the TACO Toolkit library to prepare your data. The following is the default code that the `/handlers/MyFetcher.js` files uses to get the data: ``` import { Fetcher, FetchUtils } from '@tableau/taco-toolkit/handlers' export default class MyFetcher extends Fetcher { async *fetch({ handlerInput }) { const data = handlerInput.data yield await FetchUtils.fetchJson(data.url) } } ``` ### Step 6: Configure how the data is presented Now you must define how you want to map the data to one or more or tables. This mapping of data is done in the schema. To decide how to map your data, look at your data source. When you’re done looking at the summary of the JSON data source, make the necessary edits in the `/handlers/MyParser.js` file to structure the returned data. ``` import { Parser } from '@tableau/taco-toolkit/handlers' export default class MyParser extends Parser { parse(fetcherResult, { dataContainer }) { const tableName = 'Earthquake Data' const containerBuilder = Parser.createContainerBuilder(dataContainer) const { isNew, tableBuilder } = containerBuilder.getTable(tableName) if (isNew) { tableBuilder.addColumnHeaders([ { id: 'id', dataType: 'string', }, { id: 'mag', alias: 'magnitude', dataType: 'float', }, { id: 'title', alias: 'title', dataType: 'string', }, { id: 'location', dataType: 'geometry', }, ]) } const { features } = fetcherResult if (features.length > 0) { tableBuilder.addRows( features.map(({ id, geometry: location, properties: { mag, title } }) => { return { id, mag, title, location } }) ) } return containerBuilder.getDataContainer() } } ``` Some notes: - You don’t need to write a custom parser for CSV data or for Excel data. The TACO Toolkit contains these parsers. For more information, see [Class CsvUtils](https://help.tableau.com/current/api/webdataconnector/en-us/reference/classes/handlers.CsvUtils.html) and [Class ExcelUtils](https://help.tableau.com/current/api/webdataconnector/en-us/reference/classes/handlers.ExcelUtils.html) in the SDK reference documentation. ### Step 7: Build your connector Enter these commands to build, pack, and run your new connector: ``` taco build ``` ``` taco pack ``` ``` taco run Desktop ``` **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Create an OAuth Connector 🕐 _5 min read_ The OAuth boilerplate is a connector that ingests JSON data with [ingestDataRows](https://help.tableau.com/current/api/webdataconnector/en-us/reference/classes/handlers.FetchUtils.html#ingestDataRows) Fetch API and built-in TACO data parser. ## Use cases - React - OAuth - JSON - Paginated ingestion **Note**: The OAuth connector has a dependency on the OAuth support from Tableau. This connector can’t be running with the EPS standalone server. \`taco start\`\` won’t work with OAuth connector. ## Instructions To create your OAuth connector, we recommend that you first create a boilerplate OAuth connector and edit the generated files. It’s easier to get all the files and directory structure your connector needs by just using an existing example. To create your OAuth connector, do the following steps. ### Step 1: Create a boilerplate OAuth connector 1. Enter the following command to create the connector: ``` taco create my-oauth-connector --boilerplate oauth ``` This creates a directory with the earthquake data boilerplate code, which is included with the toolkit. 2. Change directories to the `my-oauth-connector` directory. ``` cd my-oauth-connector ``` 3. Build the connector by entering the following command: ``` taco build ``` This command clears any previous or existing build caches, then installs the dependencies, then builds the frontend code and the backend code (handlers), then copies the connector.json file (the configuration file). ### Step 2: Configure your connector’s properties In your new OAuth connector directory, find and open the `connector.json` file. ``` { "name": "my-oauth-connector", "displayName": "OAuth Sample Connector", "version": "1.0.0", "tableau-version": { "min": "2023.3" }, "vendor": { "name": "vendor-name", "support-link": "https://vendor-name.com", "email": "support@vendor-name.com" }, "auth": { "type": "oauth2", "oauth": { "clientIdDesktop": "[Your client id]", "clientSecretDesktop": "[Your client secret]", "redirectUrisDesktop": [ "http://localhost:55555/Callback" ], "authUri": "[Your auth URI]", "tokenUri": "[Your token URI]", "userInfoUri": "[Your API user info URI]", "scopes": [ "Scope 1", "Scope 2" ], "capabilities": { "OAUTH_CAP_FIXED_PORT_IN_CALLBACK_URL": true, "OAUTH_CAP_CLIENT_SECRET_IN_URL_QUERY_PARAM": true, "OAUTH_CAP_PKCE_REQUIRES_CODE_CHALLENGE_METHOD": true, "OAUTH_CAP_REQUIRE_PKCE": true }, "accessTokenResponseMaps": { "ACCESSTOKEN": "access_token", "REFRESHTOKEN": "refresh_token", "access-token-issue-time": "issued_at", "access-token-expires-in": "expires_in", "username": "username" } } }, "permission": { "api": { "https://*.example.com/": [ "GET", "POST" ] } }, "window": { "height": 900, "width": 770 } } ``` - Requires auth detail Make the following changes: 1. Change the general properties. | Name | Value | | --- | --- | | name | Your connector’s directory name | | displayName | Your connector’s name. This is the name that appears in the Tableau connectors area. | | version | Your connector’s version | | min | The earliest Tableau version your connector supports | 2. Change the company properties. | Name | Value | | --- | --- | | vendor.name | Your company name | | vendor.support-link | Your company’s URL | | vendor.email | Your company’s email | 3. Change the permissions. | Name | Value | | --- | --- | | permission.api | The URI for the API that the connector is allowed to access, along with the methods (POST, GET, PUT, PATCH, DELETE) that the connector is allowed to use. | 4. Set the authentication values. | Name | Value | | --- | --- | | auth.type | Set to `oauth2` | | auth.oauth | For configuration information, see [Configuring for OAuth](https://help.tableau.com/v0.0/api/webdataconnector/en-us/docs/wdc_dev_considerations.html#configuring-for-oauth) | For more information about authentication, see the Authentication section in the [Considerations for Building Your Connector](/v0.0/api/webdataconnector/en-us/docs/wdc_dev_considerations.html) topic. 5. Change the HTML pane size. | Name | Value | | --- | --- | | window.height | The height of the connector HTML pane | | window.width | The width of the connector HTML pane | ### Step 3: Edit the user interface When you open a web data connector in Tableau, the connector displays an HTML page that links to your code and to your connector’s handlers. Optionally, this page can also display a user interface (UI) for your users to select the data that they want to download. The `/app/components/ConnectorView.tsx` file is the main component for the connector UI. You can modify or replace this file based on your connector UI requirements. ### Step 4: Edit the connector object The `/app/components/useConnector.ts` file contains a custom React [hook](https://react.dev/learn/reusing-logic-with-custom-hooks) that abstracts common connector object operations. \* The hook creates a connector object. A component can: - Track the connector object state (for example, `isInitializing`) - Directly invoke the functions returned from the hook to interact with connector object (for example, `handleSubmit`) The following is the code in `userConnector.ts` file for the connector creation. ``` const [connector] = useState( () => new Connector( (connector: Connector) => { Logger.info('Connector initialized.') const oauthCredentials = connector.oAuthCredentials setConnectorState({ ...connectorState, oauthCredentials, isInitializing: false }) }, (_: Connector, error: Error) => { Logger.error(`Connector Initialized Error: ${error.message}`) setConnectorState({ ...connectorState, errorMessage: error.message, isInitializing: false }) } ) ) ``` ### Step 5: Update the fetcher file If your data is complex and needs preprocessing, use the TACO Toolkit library to prepare your data. The following is the default code that the `/handlers/DataFetcher.ts` file uses to get the data: ``` import { Fetcher, FetchUtils, FetchOptions, DataRow, getOAuthHeader } from '@tableau/taco-toolkit/handlers' interface User { id: string name: string address: { street: string; state: string; country: string } } export default class DataFetcher extends Fetcher { async *fetch({ secrets }: FetchOptions) { // PLACEHOLDER: the url is NOT real endpoint. // Replace them with actual endpoint for corresponding file type. // Note: the permission setting in connector.json also needs to be updated accordingly. const url = 'https://www.example.com/api/user' const headers = getOAuthHeader(secrets) const users = await FetchUtils.fetchJson(url, { headers }) // Convert JSON response into DataRow[] type const rows: DataRow[] = users.map((user: User) => { const { id, name, address: { street, state, country }, } = user return { id, name, street, state, country } }) yield await FetchUtils.ingestDataRows(rows) } } ``` ### Step 6: Build your connector Enter these commands to build, pack, and run your new connector: ``` taco build ``` ``` taco pack ``` ``` taco run Desktop ``` - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [CsvUtils](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.CsvUtils.html) # Class CsvUtils #### Hierarchy - CsvUtils ##### Index ### Properties [createDataRows](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.CsvUtils.html#createDataRows) [parse](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.CsvUtils.html#parse) ## Properties ### `Static` createDataRows[](#createDataRows) createDataRows: ((rows, columnNames) => Promise<[DataRow](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.DataRow.html)\[\]\>) #### Type declaration - - (rows, columnNames): Promise<[DataRow](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.DataRow.html)\[\]\> - A utility method to convert a two-dimensional array of data into an array of [DataRow](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.DataRow.html). This function returns a Promise that resolves to an array of DataRow. #### Parameters - ##### rows: string\[\]\[\] - ##### columnNames: string\[\] #### Returns Promise<[DataRow](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.DataRow.html)\[\]\> #### Example ```ts import { CsvUtils } from '@tableau/taco-toolkit/handlers'const rows: string[][] = [ ["User1", "user1@example.com", "(555)555-5555"], ["User2", "user2@example.com", "(123)456-7890"],]const columnNames: string[] = ["Name", "Email", "Phone Number"]const result = await CsvUtils.createDataRows(rows, columnNames)// result: an array of DataRow ``` ### `Static` parse[](#parse) parse: ((rawData, options) => Promise<{     headers: string\[\] | undefined;     rows: string\[\]\[\]; }\>) #### Type declaration - - (rawData, options): Promise<{     headers: string\[\] | undefined;     rows: string\[\]\[\]; }\> - A utility method to parse CSV data into a two-dimensional array. Input data could be ArrayBuffer or string. This function returns a Promise that resolves to an object with headers and rows properties. #### Parameters - ##### rawData: string | ArrayBuffer - ##### options: {     hasHeader: boolean; } - ##### hasHeader: boolean #### Returns Promise<{     headers: string\[\] | undefined;     rows: string\[\]\[\]; }\> #### Example ```ts import { CsvUtils } from '@tableau/taco-toolkit/handlers'const rawData: string = "Name,Email,Phone Number\n" + "User1,user1@example.com,(555)555-5555\n" + "User2,user2@example.com,(123)456-7890"const { headers, rows } = await CsvUtils.parse(rawData, { hasHeader: true})// result: an object with headers and rows properties ``` ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [createDataRows](#createDataRows) - [parse](#parse) Generated using [TypeDoc](https://typedoc.org/) **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Customize Your Connector 🕐 _3 min read_ To create your connector, we recommend that you first create a sample connector and edit those files. It’s easier to get all the files and directory structure your connector needs by just using an existing example. Use the connector you created in the [Get Started](/v0.0/api/webdataconnector/en-us/index.html) topic. Copy that sample connector directory to another directory. You’re now ready to create your own connector. To create your connector, do the following steps. ## Step 1: Configure your connector’s properties In your new connector directory, find and open the `connector.json` file. ``` { "name": "my-first-connector", "version": "1.0.0", "tableau-version": { "min": "2022.3" }, "vendor": { "name": "vendor-name", "support-link": "https://vendor-name.com", "email": "support@vendor-name.com" }, "permission": { "api": { "https://*.usgs.gov/": [ "GET", "POST", "HEAD" ] } }, "auth": { "type": "none" }, "window": { "height": 800, "width": 600 } } ``` Make the following changes: 1. Change the general properties. | Name | Value | | --- | --- | | name | Your connector’s name. This is the name that appears in Tableau. | | version | Your connector’s version | | min | The earliest Tableau version your connector supports | 2. Change the company properties. | Name | Value | | --- | --- | | vendor.name | Your company name | | vendor.support-link | Your company’s URL | | vendor.email | Your company’s email | 3. Change the permissions. | Name | Value | | --- | --- | | permission.api | The URI for the API that the connector is allowed to access, along with the methods (POST, GET, PUT, PATCH, DELETE) that the connector is allowed to use. | 4. Change the auth type. | Name | Value | | --- | --- | | auth.type | Accepted values are `custom`, `oauth`, and `none`. | Use `none` for your first test connector. 5. Change the HTML pane size. | Name | Value | | --- | --- | | window.height | The height of the connector HTML pane | | window.width | The width of the connector HTML pane | ## Step 2: Create the user interface When you open a web data connector in Tableau, the connector displays an HTML page that links to your JavaScript code and to your connector’s handlers. Optionally, this page can also display a user interface for your users to select the data that they want to download. To create a user interface for your connector, open the `/app/index.html` file. ``` USGS Earthquake Feed

``` Let’s run through what the code is doing. Skipping over the standard markup for an HTML page, notice the following between the `head` tags: - The `meta` tag prevents your browser from caching the page. - The `index.css` and `toastify.min.js` files are used to simplify styling and formatting. - The `index.js` file is the code for your connector. Between the `body` tags, there’s a simple button element that illustrates how users can interact with your connector before getting data. In the next step, we’ll configure what happens when that button is clicked. ## Step 3: Edit the connector object Now that you’ve created a user interface, it’s time to edit the JavaScript code for the connector’s button. First, open the `/app/index.js` file. ``` import Connector from '@tableau/taco-toolkit' function onInitialized() { const elem = document.getElementById('submitButton') elem.innerText = 'Get Earthquake Data!' elem.removeAttribute('disabled') } const connector = new Connector(onInitialized) function submit() { connector.handlerInputs = [ { fetcher: 'MyFetcher', parser: 'MyParser', data: { url: 'https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_week.geojson', }, }, ] connector.submit() } window.addEventListener('load', function () { document.getElementById('submitButton').addEventListener('click', submit) }) ``` Some notes about the code: - Both the `fetcher` and `parser` refer to the handlers. These are JavaScript files in the `handlers` directory. These files are the backend of your connector. Keep the values the same, unless you plan to change the filenames. - Change the `url` value to the URL where you want to your connector to get your data. - The names of the fetcher and parser must match the filenames in the handlers directory. ## Step 4: Update the fetcher file If your data is complex and needs preprocessing, use the TACO Toolkit library to prepare your data. The following is the default code that the fetcher uses to get the data: ``` import { Fetcher, FetchUtils } from '@tableau/taco-toolkit/handlers' export default class MyFetcher extends Fetcher { async *fetch({ handlerInput }) { const data = handlerInput.data yield await FetchUtils.fetchJson(data.url) } } ``` ## Step 5: Configure how the data is presented Now you must define how you want to map the data to one or more or tables. This mapping of data is done in the schema. To decide how to map your data, look at your data source. When you’re done looking at the summary of the JSON data source, make the necessary edits to structure the returned data. ``` import { Parser } from '@tableau/taco-toolkit/handlers' export default class MyParser extends Parser { parse(fetcherResult, { dataContainer }) { const tableName = 'Earthquake Data' const containerBuilder = Parser.createContainerBuilder(dataContainer) const { isNew, tableBuilder } = containerBuilder.getTable(tableName) if (isNew) { tableBuilder.addColumnHeaders([ { id: 'id', dataType: 'string', }, { id: 'mag', alias: 'magnitude', dataType: 'float', }, { id: 'title', alias: 'title', dataType: 'string', }, { id: 'location', dataType: 'geometry', }, ]) } const { features } = fetcherResult if (features.length > 0) { tableBuilder.addRows( features.map(({ id, geometry: location, properties: { mag, title } }) => { return { id, mag, title, location } }) ) } return containerBuilder.getDataContainer() } } ``` ## Step 6: Build your connector Enter these commands to build, pack, and run your new connector: ``` taco build ``` ``` taco pack ``` ``` taco run Desktop ``` **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Customize Your First WDC Connector **Note**: This tutorial picks up where the [Get Started](https://help.tableau.com/v0.0/api/webdataconnector/en-us/docs/index.html) topic left off. If you haven't already, go back and set up your development environment. By the end of this tutorial, you’ll have a working WDC that connects to the [USGS Earthquake feed](http://earthquake.usgs.gov/earthquakes/feed/v1.0/index.php) and downloads data for earthquakes that occurred in the last week. You’ll learn how to: If you _really_ want to skip all of this and go straight to the source code, look for the `earthquakeUSGS` files in the `Examples` directory. You’ll get a lot more out of this if you build it from scratch though–promise! > **Note**: The connector that you create in this tutorial (`earthquakeWDC`) has a different name than the same connector in the `Examples` directory (`earthquakeUSGS`). This is to minimize the chances of accidentally overwriting the existing sample. However, if you copy the existing sample, you must change file paths. > **Note**: The browser used inside Tableau Desktop 2019.3 and earlier is QT WebKit, which does not natively support new ES6 features. If you wish to take advantage of newer features (such as promises) when building WDCs for older versions of Tableau you will need to use a polyfill. ## Create the HTML page When you open a WDC in Tableau, you display an HTML page that links to your JavaScript code and to the WDC library. Optionally, this page can also display a user interface for your users to select the data that they want to download. Create a new file named `earthquakeWDC.html` and save it in the top-level directory of the `webdataconnector` repository. (This is the same directory as the README.) Then, copy the following code into the file: ``` USGS Earthquake Feed
``` Let’s run through what the code is doing. Skipping over the standard markup for an HTML page, you’ll notice the following between the `head` tags: - The `meta` tag prevents your browser from caching the page. - The `bootstrap.min.css` and `bootstrap.min.js` files are used to simplify styling and formatting. - The `jquery.min.js` file will be used as a helper library by our connector. (For example, the connector uses jQuery to get JSON data.) - The `tableauwdc-2.3.latest.js` file is the main library for the WDC API. - The `earthquakeWDC.js` file is the (not yet created) JavaScript code for our connector. Between the `body` tags, there is a simple button element that illustrates how users can interact with your connector before getting data. In a later step, you’ll attach an event listener to the button in the JavaScript code. ## Create the connector object Now that you’ve created a user interface, it’s time to write the JavaScript code for the connector. Create a new file named `earthquakeWDC.js` and save it in the same directory as the `earthquakeWDC.html` file. Copy the following code into the file to create the basic structure of the connector: ``` (function () { var myConnector = tableau.makeConnector(); myConnector.getSchema = function (schemaCallback) { }; myConnector.getData = function (table, doneCallback) { }; tableau.registerConnector(myConnector); })(); ``` Some things to note about the code: - The code is wrapped in an immediately invoked function expression to create a local scope. - The `tableau` object isn’t defined in our code, but in the WDC library. (It’s assigned to the global scope.) - The `makeConnector` function is a constructor that predefines some methods for our connector object. - The `getSchema` and `getData` functions are placeholders for now, but will contain the logic for getting the table schema of the data and downloading the data. - The `registerConnector` function validates the connector object before initialization. ## Add an event listener Remember how we added a button to the HTML page? It’s time to create an event listener that responds to clicking on the button. Copy the following code and paste it directly below the `registerConnector` function: ``` $(document).ready(function () { $("#submitButton").click(function () { tableau.connectionName = "USGS Earthquake Feed"; tableau.submit(); }); }); ``` Here’s what is going on in the code snippet: - The jQuery `$(document).ready` function runs some code when the page loads. - An click event listener is added to the button element created earlier. The button is identified by the `submitButton` id. - The `tableau.connectionName` variable defines what we want to call the connector data source when it is displayed in Tableau. - The `tableau.submit()` function sends the connector object to Tableau for validation. **Tip**: Not every connector needs a user interface. If you want a connector to run without user input, you can use custom initialization code. For more information, see [Custom Initialization and Shutdown](/v0.0/api/webdataconnector/en-us/docs/wdc_custom_init_and_shutdown) ## Test the connector so far The connector doesn’t _do_ very much so far, but it’s enough that we can run it in the simulator. > **Note**: Have you followed the steps in the [Getting Started](/v0.0/api/webdataconnector/en-us/docs) topic to set up the simulator? This section assumes that you’ve installed dependencies already. 1. Open a command prompt or terminal in the top-level directory for the `webdataconnector` repository. 2. Run `npm start` to run the test server. 3. Open a browser and navigate to the following URL: ``` http://localhost:8888/Simulator/index.html ``` 4. In the WDC URL field, enter the path to your WDC relative to the simulator. For example, if you created your WDC in the top-level directory, you might enter: ``` ../earthquakeWDC.html ``` 5. Click the **Start Interactive Phase** button. The connector page appears in a new window. 6. Click **Get Earthquake Data!**. The connector page closes. At this point, you might be thinking “Well…did it work?” Let’s add a log message so that you can practice debugging the connector. ### Add a log message to confirm it is working (sort of) 1. In the `earthquakeWDC.js` file, copy the following code and replace the empty `myConnector.getSchema` function: ``` myConnector.getSchema = function (schemaCallback) { tableau.log("Hello WDC!"); }; ``` The `tableau.log` function allows you to pass messages from your connector back to the simulator. These log messages are then printed with the browser’s built-in `console.log()` function on the simulator page. 2. Refresh the simulator page in your browser. 3. Open your browser’s developer tools. For example, in Chrome you can press **Ctrl+Shift+I**. 4. Click **Start Interactive Phase**. 5. Click **Get Earthquake Data!**. If all goes well, you should see `Hello WDC!` in your browser’s console. ## Define a schema So the connector is working now–sort of. Before you can download data and pass it to Tableau, you need to define how you want to map the data to one or more or tables. This mapping of data is done in the schema. To decide what data you want to map in the schema, you can take a look at the USGS description of the JSON data source: [GeoJSON Summary Format](http://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php). Rather than map all the data available from the data source, this example has selected a focused subset. When you’re done looking at the summary of the JSON data source, copy the following code into the `earthquakeWDC.js` file and replace the placeholder `getSchema` function: ``` myConnector.getSchema = function (schemaCallback) { var cols = [{ id: "id", dataType: tableau.dataTypeEnum.string }, { id: "mag", alias: "magnitude", dataType: tableau.dataTypeEnum.float }, { id: "title", alias: "title", dataType: tableau.dataTypeEnum.string }, { id: "location", dataType: tableau.dataTypeEnum.geometry }]; var tableSchema = { id: "earthquakeFeed", alias: "Earthquakes with magnitude greater than 4.5 in the last seven days", columns: cols }; schemaCallback([tableSchema]); }; ``` Here’s what’s going on in the code: - The `getSchema` function takes a `schemaCallback` parameter which is defined by the WDC API. - The `cols` variable contains an array of JavaScript objects, where each object defines a single column in our table. In this example, there are columns for magnitude, title, and location. Note that for each column you can specify additional options. For example, the alias defines a friendly name that can appear in Tableau and the columnRole determines whether a field is a measure or a dimension. The `id` can only contain alphanumeric values (a-z, A-Z, 0-9) and underscore characters (`_`). The identifiers cannot contain spaces, hyphens, or special characters. For more options, see [the API reference](/v0.0/api/webdataconnector/en-us/docs/api_ref.html#webdataconnectorapi.columninfo). - The `tableSchema` variable defines the schema for a single table and contains a JavaScript object. Here, the value of the `columns` property is set to the `cols` array defined earlier. - The `schemaCallback` gets called when the schema is defined. The `schemaCallback` takes an array of table objects. In this case, there is only table object (the `tableSchema` object defined above). > **Note**: The [API Reference](/v0.0/api/webdataconnector/en-us/docs/api_ref) describes the properties that you can define for the table object and for each object in the table columns in more detail. For now, let’s plunge ahead to the exciting part–getting the data! ## Get the data Once the schema is defined, you can begin getting data and passing it to Tableau. Copy the following code and replace the placeholder `getData` function: ``` myConnector.getData = function(table, doneCallback) { $.getJSON("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/4.5_week.geojson", function(resp) { var feat = resp.features, tableData = []; // Iterate over the JSON object for (var i = 0, len = feat.length; i < len; i++) { tableData.push({ "id": feat[i].id, "mag": feat[i].properties.mag, "title": feat[i].properties.title, "location": feat[i].geometry }); } table.appendRows(tableData); doneCallback(); }); }; ``` Whew! That’s a good-sized chunk of code. Let’s see what’s happening: - The `getData` function takes two parameters: `table` and `doneCallback`. The `table` parameter is an object defined by the WDC to which you can append data. The `doneCallback` signals to Tableau that you are done getting data. - The jQuery `$.getJSON` function gets earthquake data from the USGS earthquake feed and uses a success handler to store the returned data in a response parameter (`resp`). (You can open the URL in a browser to see what the JSON data looks like.) - The `for` loop iterates over the features in the JSON object and stores the data that we want in the `tableData` array. - The `table.appendRows` function appends the `tableData` array to the `table` as a JavaScript object. ## See it in action By now, you’re a pro at [running the simulator](http://tableau.github.io/webdataconnector/docs/#run-sim), so fire it up, load your connector, and click **Get Earthquake Data!** like before. Now that we have a `getSchema` function properly defined, you should see the schema displayed in the simulator. The moment you’ve been waiting for is here! Click **Fetch Table Data** to run your `getData` function and display the results in a table. !["The earthquake data is displayed in a table on the simulator page."](/v0.0/api/webdataconnector/en-us/assets/wdc_sim_earthquake_geodata.png) > **Note** The location information for an earthquake is returned as a JSON object, which is why you might see `object Object` displayed in the simulator. Tableau 10.4 added support for geoJSON data, so while the simulator only knows you have some kind of JSON object, Tableau will have no trouble parsing the coordinates from the geometry data. To really see things working, [open your connector in Tableau](http://tableau.github.io/webdataconnector/docs/wdc_use_in_tableau): !["The earthquake data is displayed on a map in Tableau."](/v0.0/api/webdataconnector/en-us/assets/wdc_tableau_earthquake_geo_json.png) You did it! Nice work. But this is no time to rest on your laurels–[try your connector in Tableau](/v0.0/api/webdataconnector/en-us/docs/wdc_use_in_tableau), dig into the `Examples` directory to see more connectors, or read through the WDC documentation. You might want to start by learning about [connectors with multiple tables](/v0.0/api/webdataconnector/en-us/docs/wdc_multi_table_tutorial), [incremental refresh](/v0.0/api/webdataconnector/en-us/docs/wdc_incremental_refresh), and [authentication](/v0.0/api/webdataconnector/en-us/docs/wdc_authentication). See the [WDC Multiple Table Tutorial](/v0.0/api/webdataconnector/en-us/docs/wdc_multi_table_tutorial) and [WDC Node.js Proxy with OAuth Tutorial](/v0.0/api/webdataconnector/en-us/docs/wdc_oauth_tutorial.html). Better yet, dive right in and create your own connector! - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [DataContainer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataContainer.html) # Interface DataContainer #### Hierarchy - DataContainer ##### Index ### Properties [metadata](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataContainer.html#metadata) [tables](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataContainer.html#tables) ## Properties ### metadata[](#metadata) metadata: [Metadata](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.Metadata.html) ### tables[](#tables) tables: [DataTable](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html)\[\] ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [metadata](#metadata) - [tables](#tables) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [DataContainerBuilder](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataContainerBuilder.html) # Class DataContainerBuilder A builder class for constructing and modifying a DataContainer instance. This class provides methods to retrieve, and append tables within a DataContainer. #### Example ```ts const dataContainerBuilder = Parser.createContainerBuilder(initialDataContainer)// Create or get a table and add columns or rowsconst { tableBuilder, isNew } = dataContainerBuilder.getTable('myTable')tableBuilder.addColumnHeader({ name: 'column1', dataType: 'string' });tableBuilder.addColumnHeader({ name: 'column2', dataType: 'string' });tableBuilder.addRow({ column1: 'value1', column2: 'value2' });// Get the final DataContainerconst finalDataContainer = dataContainerBuilder.getDataContainer() ``` #### Hierarchy - DataContainerBuilder ##### Index ### Methods [getDataContainer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataContainerBuilder.html#getDataContainer) [getTable](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataContainerBuilder.html#getTable) ## Methods ### getDataContainer[](#getDataContainer) - getDataContainer(): [DataContainer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataContainer.html)[](#getDataContainer.getDataContainer-1) - Gets the final DataContainer instance after building and modifying it. #### Returns [DataContainer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataContainer.html) The constructed DataContainer instance. ### getTable[](#getTable) - getTable(name): {     isNew: boolean;     tableBuilder: [DataTableBuilder](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataTableBuilder.html); }[](#getTable.getTable-1) - Retrieves a table builder for the specified table name. If the table does not exist, a new table is created within the DataContainer. #### Parameters - ##### name: string The name of the table. #### Returns {     isNew: boolean;     tableBuilder: [DataTableBuilder](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataTableBuilder.html); } An object containing the table builder and a boolean indicating whether the table is newly created. - ##### isNew: boolean - ##### tableBuilder: [DataTableBuilder](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataTableBuilder.html) ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [getDataContainer](#getDataContainer) - [getTable](#getTable) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [DataRow](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.DataRow.html) # Type alias DataRow DataRow: Record Represents a single row of data in a [DataTable](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html), where each property corresponds to a column. #### Example ```ts const dataRow: DataRow = { column1: 'value1', column2: 42, column3: true, // other columns...}; ``` ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [DataTable](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html) # Interface DataTable #### Hierarchy - DataTable ##### Index ### Properties [columns](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html#columns) [id](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html#id) [name](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html#name) [properties](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html#properties) [rows](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html#rows) ## Properties ### columns[](#columns) columns: [ColumnHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.ColumnHeader.html)\[\] ### id[](#id) id: string ### name[](#name) name: string ### properties[](#properties) properties: Record ### rows[](#rows) rows: [DataRow](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.DataRow.html)\[\] ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [columns](#columns) - [id](#id) - [name](#name) - [properties](#properties) - [rows](#rows) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [DataTableBuilder](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataTableBuilder.html) # Class DataTableBuilder A builder class for constructing and modifying a DataTable instance within a DataContainer. This class provides methods to add row/s and add column header/s to a DataTable. #### Example ```ts const dataContainerBuilder = Parser.createContainerBuilder(initialDataContainer);const { tableBuilder } = dataContainerBuilder.getTable('myTable');// Add row and column header for a specific tabletableBuilder.addColumnHeader({ name: 'column1', dataType: 'string' });tableBuilder.addColumnHeader({ name: 'column2', dataType: 'string' });tableBuilder.addRow({ column1: 'value1', column2: 'value2' });// Get the final DataContainerconst finalDataContainer = dataContainerBuilder.getDataContainer(); ``` #### Hierarchy - DataTableBuilder ##### Index ### Methods [addColumnHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataTableBuilder.html#addColumnHeader) [addColumnHeaders](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataTableBuilder.html#addColumnHeaders) [addRow](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataTableBuilder.html#addRow) [addRows](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataTableBuilder.html#addRows) ## Methods ### addColumnHeader[](#addColumnHeader) - addColumnHeader(column): void[](#addColumnHeader.addColumnHeader-1) - Adds a single column header to the DataTable. #### Parameters - ##### column: [ColumnHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.ColumnHeader.html) The column header to add to the DataTable. #### Returns void ### addColumnHeaders[](#addColumnHeaders) - addColumnHeaders(colHeaders): void[](#addColumnHeaders.addColumnHeaders-1) - Adds multiple column headers to the DataTable. #### Parameters - ##### colHeaders: [ColumnHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.ColumnHeader.html)\[\] The array of column headers to add to the DataTable. #### Returns void ### addRow[](#addRow) - addRow(row): void[](#addRow.addRow-1) - Adds a single row to the DataTable. #### Parameters - ##### row: [DataRow](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.DataRow.html) The row to add to the DataTable. #### Returns void ### addRows[](#addRows) - addRows(rows): void[](#addRows.addRows-1) - Adds multiple rows to the DataTable. #### Parameters - ##### rows: [DataRow](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.DataRow.html)\[\] The array of rows to add to the DataTable. #### Returns void ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [addColumnHeader](#addColumnHeader) - [addColumnHeaders](#addColumnHeaders) - [addRow](#addRow) - [addRows](#addRows) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [DataType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.DataType.html) # Enumeration DataType The data type for a table column. ##### Index ### Enumeration Members [Bool](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.DataType.html#Bool) [Date](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.DataType.html#Date) [Datetime](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.DataType.html#Datetime) [Float](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.DataType.html#Float) [Geometry](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.DataType.html#Geometry) [Int](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.DataType.html#Int) [String](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.DataType.html#String) [Unknown](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.DataType.html#Unknown) ## Enumeration Members ### Bool[](#Bool) Bool: "bool" ### Date[](#Date) Date: "date" ### Datetime[](#Datetime) Datetime: "datetime" ### Float[](#Float) Float: "float" ### Geometry[](#Geometry) Geometry: "geometry" ### Int[](#Int) Int: "int" ### String[](#String) String: "string" ### Unknown[](#Unknown) Unknown: "unknown" ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [Bool](#Bool) - [Date](#Date) - [Datetime](#Datetime) - [Float](#Float) - [Geometry](#Geometry) - [Int](#Int) - [String](#String) - [Unknown](#Unknown) Generated using [TypeDoc](https://typedoc.org/) **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Development Overview 🕐 _2 min read_ ## Creation `taco create` Example: `taco create my-connector -b earthquake-data` The `taco create` command also provides git support with option `--git`. When you provide this option, the taco command automatically sets up the project as a git repository. **Note**: Git must be installed before using this option. ## Development Connector source code is under the connector directory, which is an [npm project](https://docs.npmjs.com/about-npm). During the development phase, taco developers mostly work under the connector directory. taco-toolkit provides standard npm support. In the connector directory, three npm scripts are available for developing connectors. - npm run build - npm start - npm run clean If you prefer working on the TACO project root directory, the TACO CLI also has corresponding commands for the npm scripts. - taco build - taco start - taco clean **Note**: if you have multiple TACO projects that depend on different versions of taco-toolkit, we recommended that you use the npm scripts. ## Tableau Integration `taco pack` To run the connector with Tableau apps, a connector must be packed into a `.taco` file. You, as a TACO developer, can run the `taco pack` command in the root directory of a TACO project. The `taco pack` command does three things: - Preparation: creating TACO XML files (according to the configurations in the `connector.json` file) - Validation: validate the `connector.json` and XML files are set up properly - Packaging: generate `.taco` file In some scenarios, you might need to manually modify the TACO XML files for customization. The following options are provided: | Option | Description | | --- | --- | | `--prepare` | When this option is present, `taco pack` only performs the prepare stage. You can use the command to create the initial TACO files for customization. | | `--validate` | When this option is present, `taco pack` only performs the validate stage. You can use the command to validate if your TACO files are set up properly. | | `--skip-prepare` | When this option is present, `taco pack` doesn’t generate the TACO files, which allows you to pack the customized TACO files into the `.taco` file. | **Note**: The TACO project must be built before packing. Developers may use taco build --clean to make sure the project has a clean build. `taco run` Example: `taco run Desktop --version 2022.3` The command launches a Tableau app with your TACO connector. By default, the command looks for `.taco` files under the current directory. You can use the `--taco-dir` option to specify a directory that contains `.taco` files. - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [ExcelUtils](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.ExcelUtils.html) # Class ExcelUtils #### Hierarchy - ExcelUtils ##### Index ### Properties [parse](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.ExcelUtils.html#parse) ## Properties ### `Static` parse[](#parse) parse: ((data) => Promise<[DataTable](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html)\[\]\>) #### Type declaration - - (data): Promise<[DataTable](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html)\[\]\> - A utility method to parse Excel data into an array of [DataTable](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html). This function returns a Promise that resolves to an array of DataTable. #### Parameters - ##### data: Uint8Array #### Returns Promise<[DataTable](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html)\[\]\> #### Example ```ts import { ExcelUtils } from '@tableau/taco-toolkit/handlers' export default class MyParser extends Parser { parse(data: Uint8Array, options: ParseOptions): DataContainer { const result = await ExcelUtils.parse(data) // result: an array of DataTable } } ``` ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [parse](#parse) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [FetchArrayBufferOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.FetchArrayBufferOptions.html) # Type alias FetchArrayBufferOptions FetchArrayBufferOptions: [FetchRequestOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchRequestOptions.html) The type for the request options of [fetchArrayBuffer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.FetchUtils.html#fetchArrayBuffer). ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [Fetcher](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Fetcher.html) # Class Fetcher`Abstract` An abstract class for implementing fetcher functionality that asynchronously retrieves data. #### Example ```ts class MyFetcher extends Fetcher { async *fetch(options: FetchOptions): AsyncGenerator { // Implementation to asynchronously retrieve data using the provided options. }} ``` #### Hierarchy - Fetcher ##### Index ### Constructors [constructor](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Fetcher.html#constructor) ### Methods [fetch](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Fetcher.html#fetch) ## Constructors ### constructor[](#constructor) - new Fetcher(): [Fetcher](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Fetcher.html)[](#constructor.new_Fetcher) - #### Returns [Fetcher](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Fetcher.html) ## Methods ### `Abstract` fetch[](#fetch) - fetch(options): AsyncGenerator[](#fetch.fetch-1) - The method to implement the fetching logic to retrieve data using the provided options. #### Parameters - ##### options: [FetchOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchOptions.html) #### Returns AsyncGenerator ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [constructor](#constructor) - [fetch](#fetch) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [FetchJsonOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.FetchJsonOptions.html) # Type alias FetchJsonOptions FetchJsonOptions: [FetchRequestOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchRequestOptions.html) The type for the request options of [fetchJson](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.FetchUtils.html#fetchJson). ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [FetchOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchOptions.html) # Interface FetchOptions #### Hierarchy - FetchOptions ##### Index ### Properties [authResult?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchOptions.html#authResult) [handlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchOptions.html#handlerInput) [secrets?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchOptions.html#secrets) ## Properties ### `Optional` authResult[](#authResult) authResult?: AuthResult ### handlerInput[](#handlerInput) handlerInput: [HandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.HandlerInput.html) ### `Optional` secrets[](#secrets) secrets?: [SecretsType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.SecretsType.html) ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [authResult](#authResult) - [handlerInput](#handlerInput) - [secrets](#secrets) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [FetchRequestOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchRequestOptions.html) # Interface FetchRequestOptions Request options for fetchJson and fetchArrayBuffer #### Hierarchy - RequestOptions - FetchRequestOptions ##### Index ### Properties [body?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchRequestOptions.html#body) [headers?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchRequestOptions.html#headers) [method?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchRequestOptions.html#method) [query?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchRequestOptions.html#query) ## Properties ### `Optional` body[](#body) body?: string | object Request body. When an object is provided for body, it will be serialized into JSON string by default. When application/x-www-form-urlencoded header is provided, the object will be serialized as query params. ### `Optional` headers[](#headers) headers?: Record Request headers. An object with key-value pair. For a `undefined` value, the corresponding header will not be added to the request. For a non-string value, it will be serialized before being added as a header. Inherited from RequestOptions.headers ### `Optional` method[](#method) method?: "GET" | "POST" HTTP method, GET or POST. Default value is GET. ### `Optional` query[](#query) query?: Record Query params. An object with key-value pair. The object will be serialized as query string and appended to the url. Inherited from RequestOptions.query ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [body](#body) - [headers](#headers) - [method](#method) - [query](#query) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [FetchUtils](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.FetchUtils.html) # Class FetchUtils #### Hierarchy - FetchUtils ##### Index ### Properties [fetchArrayBuffer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.FetchUtils.html#fetchArrayBuffer) [fetchJson](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.FetchUtils.html#fetchJson) [ingestDataRows](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.FetchUtils.html#ingestDataRows) [loadCsvData](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.FetchUtils.html#loadCsvData) [loadExcelData](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.FetchUtils.html#loadExcelData) [loadParquetData](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.FetchUtils.html#loadParquetData) ## Properties ### `Static` fetchArrayBuffer[](#fetchArrayBuffer) fetchArrayBuffer: ((url, options?) => Promise) #### Type declaration - - (url, options?): Promise - Fetch binary data from an API endpoint. The method returns a promise that resolves with an Uint8Array object. #### Parameters - ##### url: string - ##### `Optional` options: [FetchRequestOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchRequestOptions.html) #### Returns Promise #### Example ```ts import { FetchUtils } from '@tableau/taco-toolkit/handlers'const result = await FetchUtils.fetchArrayBuffer('example.com/api/file')// Result: a Uint8Array object which contains the file content ``` ### `Static` fetchJson[](#fetchJson) fetchJson: ((url, options?) => Promise) #### Type declaration - - (url, options?): Promise - Fetch data from an API endpoint. The method parses the response body as a JSON string, and returns a promise which resolves with the parsing result. #### Type Parameters - #### D = any #### Parameters - ##### url: string - ##### `Optional` options: [FetchRequestOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchRequestOptions.html) #### Returns Promise #### Example ```ts import { FetchUtils } from '@tableau/taco-toolkit/handlers'const result = await FetchUtils.fetchJson('example.com/api/user', { method: 'POST', body: { id: 'foo', }})// Result: { id: 'foo', name: 'bar' } ``` ### `Static` ingestDataRows[](#ingestDataRows) ingestDataRows: ((rows) => Promise) #### Type declaration - - (rows): Promise - Ingest a list of data with `DataRow` type into EPS data storage. The method returns a promise that resolves when data ingestion succeeds. The ingested data will be associated with the `handlerInput` that triggers the Fetcher, and uses the `name` property as the table name for the parsed data. The API must be utilized with built-in file-based parser `taco:data-file-parser` that parses the ingested data from the EPS data storage. #### Parameters - ##### rows: [DataRow](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.DataRow.html)\[\] #### Returns Promise #### Example ```ts // handlerInput{ fetcher: 'MyFetcher', // fetcher file name parser: 'taco:data-file-parser', // built-in data parser name name: 'user-table' // identifier of source object, it will be used as table name} ``` ```ts // MyFetcher.tsimport { FetchUtils, DataRow } from '@tableau/taco-toolkit/handlers'export default class MyFetcher extends Fetcher { async *fetch(options: FetchOptions) { const users = await FetchUtils.fetchJson('example.com/api/user') const rows: DataRow[] = users.map((user) => { const { id, name, address: { street, state, country } } = user return { id, name, street, state, country } }) await FetchUtils.ingestDataRows(rows) }} ``` ### `Static` loadCsvData[](#loadCsvData) loadCsvData: ((url, options?) => Promise) #### Type declaration - - (url, options?): Promise - Fetch CSV data from an API endpoint and ingest it into EPS data storage. The function returns a promise that resolves when data ingestion succeeds. The function is designated for CSV data only. For a data source that provides CSV data in multiple files (with same schema), the function may ingest the files into same table. If the multiple files all contain header line, setting the option `trimColumnHeader` to `true` will let the function skip the header line when ingesting the subsequent files. `trimColumnHeader` has no effect when loading the first file for a table. Note that loading multiple files into the same table must be performed sequentially, meaning `loadCsvData` must be called after the promise returned from the previous call is resolved. The API must be utilized with built-in file parser `taco:csv-file-parser` that parses the ingested data from the EPS data storage. #### Parameters - ##### url: string - ##### `Optional` options: [LoadCsvDataOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadCsvDataOptions.html) #### Returns Promise #### Example ```ts // handlerInput{ fetcher: 'MyFetcher', // fetcher file name parser: 'taco:csv-file-parser', // built-in csv parser name name: 'user-table' // identifier of source object, it will be used as table name} ``` ```ts // MyFetcher.tsimport { FetchUtils } from '@tableau/taco-toolkit/handlers'export default class MyFetcher extends Fetcher { async *fetch(options: FetchOptions) { yield await FetchUtils.loadCsvData('example.com/api/user.csv', { trimColumnHeader: true }) }} ``` ### `Static` loadExcelData[](#loadExcelData) loadExcelData: ((url, options?) => Promise) #### Type declaration - - (url, options?): Promise - Fetch excel data from an API endpoint and ingest it into EPS data storage. The function returns a promise that resolves when data ingestion succeeds. The function fetches the data in a stream fashion. The loaded data will be associated with the `handlerInput` that triggers the Fetcher, and the `name` property is used to identify the workbook, while the sheet names will be used as the table names. The API must be utilized with built-in excel file parser `taco:excel-file-parser` that parses the ingested data from the EPS data storage. #### Parameters - ##### url: string - ##### `Optional` options: [LoadDataOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html) #### Returns Promise #### Example ```ts // handlerInput{ fetcher: 'MyFetcher', // fetcher file name parser: 'taco:excel-file-parser', // built-in parser name name: 'user-table' // identifier of source object, which will be used to identify the workbook} ``` ```ts // MyFetcher.tsimport { FetchUtils } from '@tableau/taco-toolkit/handlers'export default class MyFetcher extends Fetcher { async *fetch(options: FetchOptions) { yield await FetchUtils.loadExcelData('example.com/api/user.xls') }} ``` ### `Static` loadParquetData[](#loadParquetData) loadParquetData: ((url, options?) => Promise) #### Type declaration - - (url, options?): Promise - Fetch parquet data from an API endpoint and ingest it into EPS data storage. The function returns a promise that resolves when data ingestion succeeds. The function fetches the data in a stream fashion. The loaded data will be associated with the `handlerInput` that triggers the Fetcher, and uses the `name` property as the table name for the parsed data fetched from API endpoint/s. The API must be utilized with built-in parquet file parser `taco:parquet-file-parser` that parses the ingested data from the EPS data storage. #### Parameters - ##### url: string - ##### `Optional` options: [LoadDataOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html) #### Returns Promise #### Example ```ts // handlerInput{ fetcher: 'MyFetcher', // fetcher file name parser: 'taco:parquet-file-parser', // built-in parser name name: 'user-table' // identifier of source object, which will be used as table name} ``` ```ts // MyFetcher.ts for single API endpointimport { FetchUtils } from '@tableau/taco-toolkit/handlers'export default class MyFetcher extends Fetcher { async *fetch(options: FetchOptions) { yield await FetchUtils.loadParquetData('example.com/api/user.parquet') }} ``` Note: The API can also be used to fetch parquet data from multiple API endpoints and append the data together into a single table. The `name` property from the `handlerInput` will be used as the table name for the parsed data fetched from multiple API endpoint. #### Example ```ts // MyFetcher.ts for multiple API endpointsimport { FetchUtils } from '@tableau/taco-toolkit/handlers'export default class MyFetcher extends Fetcher { async *fetch(options: FetchOptions) { const urls = [ 'example.com/api/user1.parquet', 'example.com/api/user2.parquet', 'example.com/api/user3.parquet' ] const promises = urls.map((url) => FetchUtils.loadParquetData(url)) await Promise.all(promises) yield }} ``` ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [fetchArrayBuffer](#fetchArrayBuffer) - [fetchJson](#fetchJson) - [ingestDataRows](#ingestDataRows) - [loadCsvData](#loadCsvData) - [loadExcelData](#loadExcelData) - [loadParquetData](#loadParquetData) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [FileBasedHandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FileBasedHandlerInput.html) # Interface FileBasedHandlerInput The object type sent by the connector app to handlers for data source with large data. #### Type Parameters - #### Data #### Hierarchy - [BasicHandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html) - FileBasedHandlerInput ##### Index ### Properties [auth?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FileBasedHandlerInput.html#auth) [data](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FileBasedHandlerInput.html#data) [fetcher](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FileBasedHandlerInput.html#fetcher) [name](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FileBasedHandlerInput.html#name) [parser](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FileBasedHandlerInput.html#parser) ## Properties ### `Optional` auth[](#auth) auth?: string File name of connector authenticator Inherited from [BasicHandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html).[auth](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html#auth) ### data[](#data) data: Data Arbitrary data sent to the connector fetcher Inherited from [BasicHandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html).[data](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html#data) ### fetcher[](#fetcher) fetcher: string File name of connector fetcher Inherited from [BasicHandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html).[fetcher](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html#fetcher) ### name[](#name) name: string Identifier of source object, will be used as table name ### parser[](#parser) parser: [TacoFileParserName](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.TacoFileParserName.html) Built-in parser name Overrides [BasicHandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html).[parser](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html#parser) ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [auth](#auth) - [data](#data) - [fetcher](#fetcher) - [name](#name) - [parser](#parser) Generated using [TypeDoc](https://typedoc.org/) **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Framework and Toolkit Versioning 🕐 _4 min read_ ## WDC 3.0 versioning considerations There are several components of the Web Data Connector (WDC) 3.0 framework that are independently versioned and can affect the forward or backwards compatibility of connectors developed using the framework. Those components are: - Tableau products: Tableau Desktop, Tableau Server, Tableau Prep, and so on - taco-toolkit: CLI/tookit used to develop connectors - .taco project and file: The connector development project and the resulting packaged connector itself Based on the versioning of these components, there are some principles to keep in mind when developing connectors: - The taco-toolkit version will always align with a particular Tableau product version. - A connector project and resulting packaged connector (.taco) will have a minimum version of Tableau that it’s compatible with, depending on the version of taco-toolkit that it’s developed with. Bug fixes and the addition of new features or capabilities to the WDC 3.0 framework might require an update to Tableau products, taco-toolkit, the connector, or all of them at once. From a developer perspective, updating a connector to apply a bug fix or new feature requires you to update taco-toolkit and your Tableau product version. So, let’s say that a new WDC 3.0 capability is introduced in the latest version of Tableau and a corresponding new version of taco-toolkit is published. What do you do as a developer? There are several possibilities: 1. To use the new capability, implement the required connector code changes and rebuild your connector using the latest taco-toolkit. This makes the connector incompatible with versions of Tableau earlier than the minimum version specified by the toolkit. 1. Update taco-toolkit (npm install the latest package) 2. Run `taco build` on the existing project. This step will fail and inform you of elements in the connector that must be updated. 3. Make any necessary code changes to the connector. 4. Run `taco build` again to ensure success. 5. Run `taco pack` to create a new `.taco` file, and then taco run if you wish to test the connector 2. If you don’t want to implement the new capability, and there are no other required code/API changes, you can still update taco-toolkit to the latest and use it to modify and rebuild your connector. However, again, this makes the connector incompatible with versions of Tableau earlier than the minimum version specified by the toolkit. 3. You have the option to not update taco-toolkit and continue maintaining your connector using the version of taco-toolkit that you currently have. However, if breaking changes were introduced in the latest taco-toolkit and Tableau version, your connector might not be compatible with the latest version of Tableau products. There are some implications that can be taken away from the preceding information: - Forward compatibility of a connector isn’t guaranteed. - You could end up with multiple versions of a connector that are compatible with different ranges of Tableau product versions. - Maintaining only the latest version of a connector, or multiple versions, is up to you. However, maintaining multiple versions of a connector also means you must keep and run multiple versions of taco-toolkit ## TACO-Toolkit versioning The @tableau/taco-toolkit npm package uses the standard npm semantic versioning model. Major and minor toolkit version releases correspond with Tableau major releases. Patch toolkit version releases may or may not correspond with Tableau maintenance releases, depending on if any changes are required in the Tableau product maintenance release. Corresponding released Tableau product versions will be provided as npm distribution tags (for example, tableau-2022.3, tableau-2022.3.1). - _Major_ version (_x_.0.0) increment: - Releases on Tableau major release date - The package has new features and isn’t backwards compatible with previous Tableau product versions - The version is tagged with a Tableau major version (for example, `tableau-2022.3`) - _Minor_ version (1._x_.0) increment: - Releases on Tableau major release date - The package has new features and is backwards compatible - The version is tagged with a Tableau major version (for example, `tableau-2022.3`) - _Patch_ version (1.0._x_) increment (minor fixes that require Tableau product maintenance release): - Releases on Tableau patch release date - The package has minor bug fixes and is backwards compatible - The version is tagged with a Tableau patch version (for example, `tableau-2022.3.1`) - _Patch_ version (1.0._x_) increment (taco-toolkit only minor fixes): - Does not correspond with a Tableau release - The package has minor bug fixes and is backwards compatible - The version is tagged with the latest tag for the same Tableau release To install a specific version of @tableau/taco-toolkit, you may use - @tableau/taco-toolkit@ to install with Tableau version - @tableau/taco-toolkit@ to install with package version For example, to install TACO CLI for Tableau 2022.3: - npm install -g @tableau/taco-toolkit@tableau-2022.3 - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [GeographicRole](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html) # Enumeration GeographicRole The geographic role for a table column. ##### Index ### Enumeration Members [AreaCode](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html#AreaCode) [CbsaMsa](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html#CbsaMsa) [City](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html#City) [CongressionalDistrict](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html#CongressionalDistrict) [CountryRegion](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html#CountryRegion) [County](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html#County) [Latitude](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html#Latitude) [Longitude](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html#Longitude) [StateProvince](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html#StateProvince) [ZipCodePostcode](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html#ZipCodePostcode) ## Enumeration Members ### AreaCode[](#AreaCode) AreaCode: "area\_code" ### CbsaMsa[](#CbsaMsa) CbsaMsa: "cbsa\_msa" core-based statistical area / metropolitan statistical area ### City[](#City) City: "city" ### CongressionalDistrict[](#CongressionalDistrict) CongressionalDistrict: "congressional\_district" ### CountryRegion[](#CountryRegion) CountryRegion: "country\_region" ### County[](#County) County: "county" ### Latitude[](#Latitude) Latitude: "latitude" ### Longitude[](#Longitude) Longitude: "longitude" ### StateProvince[](#StateProvince) StateProvince: "state\_province" ### ZipCodePostcode[](#ZipCodePostcode) ZipCodePostcode: "zip\_code\_postcode" ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [AreaCode](#AreaCode) - [CbsaMsa](#CbsaMsa) - [City](#City) - [CongressionalDistrict](#CongressionalDistrict) - [CountryRegion](#CountryRegion) - [County](#County) - [Latitude](#Latitude) - [Longitude](#Longitude) - [StateProvince](#StateProvince) - [ZipCodePostcode](#ZipCodePostcode) Generated using [TypeDoc](https://typedoc.org/) **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Get Data - Best Practices 🕐 _5 min read_ In the WDC Gather Data Phase, it’s a best practice to insert data into the extract you create in manageable amounts. This is often called _data chunking_ or _paging_ and it can help improve performance and can keep the WDC from overloading Tableau, and can provide a better experience for end users because they can see regular progress indicators. This best practice is important when you’re working with large data sets. **Note:** In Tableau 2019.4 and later, Web Data Connectors use Qt WebEngine as the internal browser. The version of the Qt WebEngine we currently use has a limitation in its data communication channel of approximately 128 MB. If your WDC appends more data than can be transmitted at one time, the WDC is created and initialized, but no data is added. To avoid this problem, be sure to insert your data in chunks that are less than 128 MB. For more information about this issue, see [Troubleshoot WDC WebEngine Issues in Tableau 2019.4 and later](/v0.0/api/webdataconnector/en-us\docs\wdc_webengine.html). This topic describes an approach that could be used to add data in chunks during the WDC Gather Data Phase. * * * **In this section:** * * * ## Append rows in the WDC Gather Data Phase You might recall from the WDC lifecyle diagram shown in [WDC Lifecyle and Phases](/v0.0/api/webdataconnector/en-us/docs/wdc_phases.html), the WDC Gather Data Phase includes the call to `getData`, which is called once for each schema (or table). Within that `getData` function call, you can call `table.appendRows` as many times as you need to append data to the table that is created. The `appendRows` function allows you to insert your data in manageable chunks. ![](/v0.0/api/webdataconnector/en-us/assets/wdc_flow_data.png) The diagram legend is as follows. ![](/v0.0/api/webdataconnector/en-us/assets/wdc_flow_legend.png) ## Determine how to split your data How you determine the amount of data to append at a time depends upon the overall size of your data. If your data is large (over 128 MB, for example), you’ll need to break it down in to smaller chunks. If your data set is small, you might not need to chunk it at all. The `appendRows` function has one parameter, which can be an array of arrays or an array of objects. A common way to split the data is by having the same number of rows in each chunk. Some rows may be larger in size than others, so you may have to iterate to find an appropriate number of rows. The following `appendRows` example shows how you might create a size variable and use that with a row count variable to iterate through the data. Rather than building the extract all at once with the call to `table.appendRows`, the WDC uses a `while` loop to call the `appendRows` function iteratively based on the row index and the size we chose to increment. In this example, we use a size variable that is an arbitrary integer that determines how much of the data to append. It represents the number of items in the array to add at one time. In this example, we use the JavaScript `slice` function to split the `tableData` array into smaller chunks. The size we use is 100, so 100 rows from the `tableData` array are added to the extract at a time. For large data sets, you would probably want to use a larger value to improve the performance. Be sure to use a size value that keeps amount of data added in each `appendRows` call under 128 MB. ``` // called inside the getData function // after we populate the tableData var row_index = 0; var size = 100; while (row_index < tableData.length){ table.appendRows(tableData.slice(row_index, size + row_index)); row_index += size; tableau.reportProgress("Getting row: " + row_index); } ``` ## Use the reportProgress function to log your commits The `appendRows` example also uses the `reportProgress` function. This function allows you to follow the progress of the Gather Data phase in Tableau. It’s a best practice to call this function as you add your data to the extract. Note that the `reportProgress` function is intended to inform Tableau Desktop users. Tableau Server users won’t see the message, and calling the `reportProgress` function with a high frequency could adversely affect performance. Note also that calling `console.log` or `tableau.log` in a similar manner with high frequency could also affect performance. ``` tableau.reportProgress("Getting row: " + row_index); ``` The progress is displayed in Tableau. For example, when you first load your WDC you’re taken to the **Data Source** pane. When you click the **Sheet 1** tab for the first time, the worksheet opens and the Create Extract dialog box appears and reports the progress. This can be helpful when you’re loading a large data set. With a small data set, the extract creation process goes quickly, so you might not see the progress dialog if the size increment you use is large. ![](/v0.0/api/webdataconnector/en-us/assets/wdc_tableau.reportProgress.png) * * * ## Example code: EarthquakeUSGS The following example is based on the [Tutorial](/v0.0/api/webdataconnector/en-us/docs/wdc_data_tutorial.html) and the EarthquakeUSGS sample. It’s a slightly modified version of the `earthquakeUSGS.js` file you created in the tutorial. In this case, rather than building the extract all at once with the call to `table.appendRows`, the WDC uses a `while` loop to call the `appendRows` function iteratively based on the row index and the size we chose to increment. The example also looks at a larger data set, in this case all the earthquakes (of any size) reported in the last month. In this example, we create a function called _chunkData_ that is a wrapper for the `while` loop we used in the previous example. Our _chunkData_ function is called from the WDC `getData` function. You could create a function similar to this in your own WDC. Our _chunkData_ function takes `table` and `tableData` as arguments. In our function, we use a _size_ variable, which is an arbitrary integer value that we use to determine how much of the data we want to append. The data set we’re using isn’t large (less than 8 MB). In this case, we chose 100 but you might need to use a larger value in your own function for better performance. Progress is reported as each row is added. * * * ``` (function() { // Create the connector object var myConnector = tableau.makeConnector(); // Define the schema myConnector.getSchema = function(schemaCallback) { var cols = [{ id: "id", dataType: tableau.dataTypeEnum.string }, { id: "mag", alias: "magnitude", dataType: tableau.dataTypeEnum.float }, { id: "title", alias: "title", dataType: tableau.dataTypeEnum.string }, { id: "location", dataType: tableau.dataTypeEnum.geometry }]; var tableSchema = { id: "earthquakeFeed", alias: "All earthquakes in the last 30 days", columns: cols }; schemaCallback([tableSchema]); }; // Download the data myConnector.getData = function(table, doneCallback) { $.getJSON("https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.geojson", function(resp) { var feat = resp.features, tableData = []; // Iterate over the JSON object for (var i = 0, len = feat.length; i < len; i++) { tableData.push({ "id": feat[i].id, "mag": feat[i].properties.mag, "title": feat[i].properties.title, "location": feat[i].geometry }); } // add the data chunkData(table, tableData); doneCallback(); }); }; // add the data in manageable chunks function chunkData(table, tableData){ var row_index = 0; var size = 100; while (row_index < tableData.length){ table.appendRows(tableData.slice(row_index, size + row_index)); row_index += size; tableau.reportProgress("Getting row: " + row_index); } } tableau.registerConnector(myConnector); // Create event listeners for when the user submits the form $(document).ready(function() { $("#submitButton").click(function() { tableau.connectionName = "USGS Earthquake Feed"; // This will be the data source name in Tableau tableau.submit(); // This sends the connector object to Tableau }); }); })(); ``` **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Get Started 🕐 _3 min read_ Create a web data connector when you want to connect to a web data source from Tableau. A web data connector is a packaged connector containing web elements. It connects to web data (for example, by means of a REST API), converts the data to a JSON format, and passes the data to Tableau. **Note**: The TACO Toolkit, which helps you build your connectors, is only available for Windows and macOS. Linux is not supported. ## Build a sample web data connector This section guides you through the process of setting up your development environment and building a sample web data connector in the simulator. To best understand what a web data connector is, we recommend that you build a sample connector using a boilerplate included in the Taco Toolkit. To build a sample connector, perform the following tasks. 1. Make sure you have the following dependencies installed: - [Node version 16 and npm version 7 and above](https://nodejs.org/en/download/) - [Python 3.7 or higher](https://www.python.org/downloads/) - [JDK 11 or higher](https://www.oracle.com/java/technologies/downloads/) **OS Notes**: - If you're using Windows and installing Node.js, we recommend that you click the option to install the Python and Visual Studio Build Tools. - For macOS, you must install XCode Command Line Tools. If you don't already have it installed, you can install XCode Command Line Tools standalone by running \`xcode-select --install\` in Terminal or, alternatively, install the \[full version of XCode\](https://developer.apple.com/xcode/). 2. Install the TACO Toolkit by opening your terminal and typing the following command: ``` npm install -g @tableau/taco-toolkit@tableau- ``` Where `version` is your version of Tableau. For example: ``` npm install -g @tableau/taco-toolkit@tableau-2024.1 ``` This command installs the toolkit globally. The Taco Toolkit includes: - Taco CLI - Web data connector boilerplate connector - Web data connector 3.0 SDK - Various utilities for building, packaging, and signing your connectors 3. Verify the install by typing the following: ``` taco ``` This command returns the CLI version. 4. Create a parent directory for your connectors and navigate to that directory. 5. Enter the following command to create the connector: ``` taco create my-first-connector --boilerplate earthquake-data ``` This creates a directory with the earthquake data boilerplate code, which is included with the toolkit. 6. Change directories to the myConnector directory. ``` cd my-first-connector ``` 7. Build the connector by entering the following command: ``` taco build ``` This command clears any previous or existing build caches, then installs the dependencies, then builds the frontend code and the backend code (handlers), then copies the connector.json file (the configuration file). 8. Create the Taco file ``` taco pack ``` This creates the .taco file 9. Type the following command to run the connector: ``` taco run Desktop ``` This starts Tableau Desktop with the appropriate command-line parameters pointing it to your newly created connector. 10. Launch the connector in Tableau Desktop. You’ll see a link to your connector in Tableau’s list of connectors, **my-first-connector by vendor-name**. To see your dialog, click the link. ![Tableau Desktop showing the new connector](/tableau/next/en-us/api/webdataconnector/en-us/assets/connector_in_tableau.png) Tableau loads your default system browser to show the connector user interface (UI). This is the interactive phase. 11. Click the **Get Earthquake Data** button. Clicking this button closes the browser pane. A Tableau worksheet opens with your connected data. ## What’s next? You can [customize your connector](/v0.0/api/webdataconnector/en-us/docs/wdc_customize_connector.html) with your own information. Or, if you’re ready to make your own connector, you can use one the [connector boilerplates](/v0.0/api/webdataconnector/en-us/docs/wdc_samples.html) to make your own. - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [getAuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/functions/app.getAuthHeader.html) # Function getAuthHeader - getAuthHeader(token, prefix?): [AuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.AuthHeader.html)[](#getAuthHeader) - Generates an authentication header using the provided token and optional prefix. #### Parameters - ##### token: string The token used for authentication. - ##### prefix: string = 'Bearer' The prefix to be added before the token (default is 'Bearer'). #### Returns [AuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.AuthHeader.html) The authentication header. #### Example ``` //Generating a custom prefix token headerconst token = 'your-custom-token';const customPrefix = 'Custom';const header = getAuthHeader(token, customPrefix);// header will be: { Authorization: 'Custom your-custom-token' } ``` ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [getBasicAuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/functions/app.getBasicAuthHeader.html) # Function getBasicAuthHeader - getBasicAuthHeader(username, password): [AuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.AuthHeader.html)[](#getBasicAuthHeader) - Generates a Basic authentication header using the provided username and password. #### Parameters - ##### username: string The username for authentication. - ##### password: string The password for authentication. #### Returns [AuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.AuthHeader.html) The Basic authentication header. #### Example ``` // Generating a Basic authentication headerconst username = 'yourUsername';const password = 'yourPassword';const basicAuthHeader = getBasicAuthHeader(username, password);console.log(basicAuthHeader);// Output will be: { Authorization: 'Basic base64EncodedString' } ``` ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [getOAuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/functions/app.getOAuthHeader.html) # Function getOAuthHeader - getOAuthHeader(headers): [AuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.AuthHeader.html)[](#getOAuthHeader) - Generates an OAuth authentication header based on the provided secrets. If no access token is provided in the secrets, an empty object is returned. #### Parameters - ##### headers: undefined | [SecretsType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.SecretsType.html) The headers containing access-token. #### Returns [AuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.AuthHeader.html) The authentication header. ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [HandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.HandlerInput.html) # Type alias HandlerInput HandlerInput: [BasicHandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html) | [FileBasedHandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FileBasedHandlerInput.html) Represents an input type for handlers, allowing flexibility between basic and file-based inputs. #### Type Parameters - #### Data = any The type of data that the handler input can carry. #### Example ```ts // Usage with basic handler inputconst basicHandlerInputObj: HandlerInput = { fetcher: 'my-fetcher', parser: 'my-parser', data: [],}// Usage with file-based handler inputconst fileBasedHandlerInputObj: HandlerInput = { fetcher: 'my-fetcher', parser: // "taco:excel-file-parser" | "taco:csv-file-parser" | "taco:parquet-file-parser" | "taco:data-file-parser", data: [], name: 'table-name',} ``` ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) # Module handlers ##### Index ### References [AggType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html#AggType) [ColumnRole](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html#ColumnRole) [ColumnType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html#ColumnType) [DataType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html#DataType) [GeographicRole](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html#GeographicRole) [HandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html#HandlerInput) [NumberFormat](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html#NumberFormat) [UnitsFormat](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html#UnitsFormat) [getAuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html#getAuthHeader) [getBasicAuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html#getBasicAuthHeader) [getOAuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html#getOAuthHeader) ### Classes [AsyncParser](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.AsyncParser.html) [Auth](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Auth.html) [CsvUtils](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.CsvUtils.html) [DataContainerBuilder](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataContainerBuilder.html) [DataTableBuilder](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataTableBuilder.html) [ExcelUtils](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.ExcelUtils.html) [FetchUtils](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.FetchUtils.html) [Fetcher](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Fetcher.html) [ParquetUtils](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.ParquetUtils.html) [Parser](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Parser.html) ### Interfaces [AuthenticateOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.AuthenticateOptions.html) [BasicHandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.BasicHandlerInput.html) [DataContainer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataContainer.html) [DataTable](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html) [FetchOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchOptions.html) [FetchRequestOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FetchRequestOptions.html) [FileBasedHandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.FileBasedHandlerInput.html) [LoadCsvDataOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadCsvDataOptions.html) [LoadDataOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html) [ParseOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.ParseOptions.html) ### Type Aliases [ColumnHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.ColumnHeader.html) [DataRow](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.DataRow.html) [FetchArrayBufferOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.FetchArrayBufferOptions.html) [FetchJsonOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.FetchJsonOptions.html) [Metadata](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.Metadata.html) [TacoFileParserName](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.TacoFileParserName.html) ### Functions [log](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/functions/handlers.log.html) ## References ### AggType[](#AggType) Re-exports [AggType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.AggType.html) ### ColumnRole[](#ColumnRole) Re-exports [ColumnRole](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.ColumnRole.html) ### ColumnType[](#ColumnType) Re-exports [ColumnType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.ColumnType.html) ### DataType[](#DataType) Re-exports [DataType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.DataType.html) ### GeographicRole[](#GeographicRole) Re-exports [GeographicRole](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.GeographicRole.html) ### HandlerInput[](#HandlerInput) Re-exports [HandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.HandlerInput.html) ### NumberFormat[](#NumberFormat) Re-exports [NumberFormat](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.NumberFormat.html) ### UnitsFormat[](#UnitsFormat) Re-exports [UnitsFormat](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.UnitsFormat.html) ### getAuthHeader[](#getAuthHeader) Re-exports [getAuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/functions/app.getAuthHeader.html) ### getBasicAuthHeader[](#getBasicAuthHeader) Re-exports [getBasicAuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/functions/app.getBasicAuthHeader.html) ### getOAuthHeader[](#getOAuthHeader) Re-exports [getOAuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/functions/app.getOAuthHeader.html) ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [AggType](#AggType) - [ColumnRole](#ColumnRole) - [ColumnType](#ColumnType) - [DataType](#DataType) - [GeographicRole](#GeographicRole) - [HandlerInput](#HandlerInput) - [NumberFormat](#NumberFormat) - [UnitsFormat](#UnitsFormat) - [getAuthHeader](#getAuthHeader) - [getBasicAuthHeader](#getBasicAuthHeader) - [getOAuthHeader](#getOAuthHeader) Generated using [TypeDoc](https://typedoc.org/) **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Join Filtering When you connect to multiple tables of data with a web data connector, you can filter the data from one table based on the data from another table. Said another way, you can make one table dependent on the data returned from another table. Use join filtering to improve the efficiency of your connectors by getting only the data that you want. Otherwise, by default, Tableau gets all data from all tables. Before you set up join filtering, ensure that you have a working web data connector for your tables. For more information on getting data from multiple tables, see the [Multiple Tables Tutorial](/v0.0/api/webdataconnector/en-us/docs/wdc_multi_table_tutorial). Once you have a working connector for multiple tables, step through the following example to understand join filtering (or review the example connector at the end). **Important:** Join filtering is only supported in WDC versions 2.2 and later. ### Create a sample schema In this example, you create a connector for blog post data where you join two tables: a users table and a posts table. You can use join filtering to first get data from the users table, then only get post data that corresponds to certain users. Here is an example schema for the users table and posts table: ``` var users_cols = [{ id: "id", dataType: tableau.dataTypeEnum.string }, { id: "name", alias: "name", dataType: tableau.dataTypeEnum.string }]; var usersTable = { id: "users", alias: "User Data", columns: users_cols }; var posts_cols = [{ id: "id", dataType: tableau.dataTypeEnum.string }, { id: "userId", alias: "userId", dataType: tableau.dataTypeEnum.string }, { id: "title", alias: "title", dataType: tableau.dataTypeEnum.string }]; var postsTable = { id: "posts", alias: "Post Data", columns: posts_cols }; ``` ### Specify schema properties Now that you have a sample schema, you can specify which tables you want join and which columns you want to use for the primary to foreign key relationship. To filter posts by user, set the following schema properties: - `joinOnly`. (Optional) Whether you want to make join filtering required for this table. If you set this value to true, you cannot connect to the table without first connecting to the other table. For example, if you set this to true for the `posts` table, the `posts` table is disabled in Tableau unless you select the `users` table first. - `filterable`. Set to true for the column that you want to use for filtering. Because we want the `posts` tables to be filtered on its `userId` column, you want to set this to true for the `userId` column of the `posts` table. - `foreignKey`. Specify the `tableId` and `columnId` to create the primary to foreign key relationship. The `posts` table `userId` column represents a foreign key to the `users` table `id` primary key. Set the `foreignKey` property on the `userId` column of the `posts` table and point to the primary key: `foreignKey: { "tableId": "users", "columnId": "id" }`. You can have many foreignKey attributes point to the same primary key. The schema below has these properties already set: ``` var users_cols = [{ id: "id", dataType: tableau.dataTypeEnum.string, }, { id: "name", alias: "name", dataType: tableau.dataTypeEnum.string }]; var usersTable = { id: "users", alias: "User Data", columns: users_cols }; // Schema for posts var posts_cols = [{ id: "id", dataType: tableau.dataTypeEnum.string }, { id: "userId", alias: "userId", dataType: tableau.dataTypeEnum.string, filterable: true, foreignKey: { "tableId": "users", "columnId": "id" } }, { id: "title", alias: "title", dataType: tableau.dataTypeEnum.string }]; var postsTable = { joinOnly: true, id: "posts", alias: "Post Data", columns: posts_cols }; ``` ### Get data for tables Because the table that you want to filter depends on data from another table, you need to include additional logic to iterate over the filter values. The dependent table includes the following properties that you can use: - `isJoinFiltered`. Whether the table can be used for join filtering. If the schema properties are set correctly, this equals true. - `filterValues`. An array of the values to use for filtering. For example, an array of the user ID values to get data for. For example, you might iterate through the user ID filter values with the following `getData` function: ``` myConnector.getData = function(table, doneCallback) { var tableData = []; if (table.tableInfo.id === "users") { $.getJSON("http://jsonplaceholder.typicode.com/users", function(resp) { for (var i = 0; i < resp.length; i++) { // Only return the first 5 users to demonstrate filtering if (resp[i].id <= 5) { tableData.push({ "id": resp[i].id, "name": resp[i].name }); } } table.appendRows(tableData); doneCallback(); }); } else if (table.tableInfo.id === "posts") { var filterValues = table.filterValues; if (!table.isJoinFiltered) { tableau.abortWithError("The table must be filtered first."); return; } if (filterValues.length === 0) { doneCallback(); return; } var postFetches = []; // Now that we have the ids of the filtered users, // get the posts for only those users. for (var userId in filterValues) { var postFetch = new Promise(function(resolve, reject) { $.getJSON("http://jsonplaceholder.typicode.com/posts?userId=" + userId, function(resp) { for (var i = 0; i < resp.length; i++) { tableData.push({ "id": resp[i].id, "userId": resp[i].userId, "title": resp[i].title }); } table.appendRows(tableData); resolve(); }); }); postFetches.push(postFetch); } Promise.all(postFetches).then(function(values) { doneCallback(); }) } }; ``` ### Full example The full code for the example above is displayed below: ``` (function() { // Create the connector object var myConnector = tableau.makeConnector(); // Define the schema myConnector.getSchema = function(schemaCallback) { // Schema for users var users_cols = [{ id: "id", dataType: tableau.dataTypeEnum.string, }, { id: "name", alias: "name", dataType: tableau.dataTypeEnum.string }]; var usersTable = { id: "users", alias: "User Data", columns: users_cols }; // Schema for posts var posts_cols = [{ id: "id", dataType: tableau.dataTypeEnum.string }, { id: "userId", alias: "userId", dataType: tableau.dataTypeEnum.string, filterable: true, foreignKey: { "tableId": "users", "columnId": "id" } }, { id: "title", alias: "title", dataType: tableau.dataTypeEnum.string }]; var postsTable = { joinOnly: true, id: "posts", alias: "Post Data", columns: posts_cols }; schemaCallback([usersTable, postsTable]); }; // Download the data myConnector.getData = function(table, doneCallback) { var tableData = []; if (table.tableInfo.id === "users") { $.getJSON("http://jsonplaceholder.typicode.com/users", function(resp) { for (var i = 0; i < resp.length; i++) { // Only return the first 5 users to demonstrate filtering if (resp[i].id <= 5) { tableData.push({ "id": resp[i].id, "name": resp[i].name }); } } table.appendRows(tableData); doneCallback(); }); } else if (table.tableInfo.id === "posts") { var filterValues = table.filterValues; if (!table.isJoinFiltered) { tableau.abortWithError("The table must be filtered first."); return; } if (filterValues.length === 0) { doneCallback(); return; } var postFetches = []; // Now that we have the ids of the filtered users, // get the posts for only those users. for (var userId in filterValues) { var postFetch = new Promise(function(resolve, reject) { $.getJSON("http://jsonplaceholder.typicode.com/posts?userId=" + userId, function(resp) { for (var i = 0; i < resp.length; i++) { tableData.push({ "id": resp[i].id, "userId": resp[i].userId, "title": resp[i].title }); } table.appendRows(tableData); resolve(); }); }); postFetches.push(postFetch); } Promise.all(postFetches).then(function(values) { doneCallback(); }) } }; tableau.registerConnector(myConnector); // Create event listeners for when the user submits the form $(document).ready(function() { $("#submitButton").click(function() { tableau.connectionName = "JSONPlaceholder"; // This will be the data source name in Tableau tableau.submit(); // This sends the connector object to Tableau }); }); })(); ``` - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [LoadCsvDataOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadCsvDataOptions.html) # Interface LoadCsvDataOptions #### Hierarchy - [LoadDataOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html) - LoadCsvDataOptions ##### Index ### Properties [body?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadCsvDataOptions.html#body) [headers?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadCsvDataOptions.html#headers) [method?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadCsvDataOptions.html#method) [query?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadCsvDataOptions.html#query) [trimColumnHeader?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadCsvDataOptions.html#trimColumnHeader) ## Properties ### `Optional` body[](#body) body?: string | object Inherited from [LoadDataOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html).[body](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html#body) ### `Optional` headers[](#headers) headers?: Record Inherited from [LoadDataOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html).[headers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html#headers) ### `Optional` method[](#method) method?: "GET" | "POST" Inherited from [LoadDataOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html).[method](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html#method) ### `Optional` query[](#query) query?: Record Query params. An object with key-value pair. The object will be serialized as query string and appended to the url. Inherited from [LoadDataOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html).[query](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html#query) ### `Optional` trimColumnHeader[](#trimColumnHeader) trimColumnHeader?: boolean If this attribute is set to true, it will remove subsequent column headers from next chunk before writing to disk ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [body](#body) - [headers](#headers) - [method](#method) - [query](#query) - [trimColumnHeader](#trimColumnHeader) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [LoadDataOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html) # Interface LoadDataOptions #### Hierarchy - RequestOptions - LoadDataOptions - [LoadCsvDataOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadCsvDataOptions.html) ##### Index ### Properties [body?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html#body) [headers?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html#headers) [method?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html#method) [query?](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.LoadDataOptions.html#query) ## Properties ### `Optional` body[](#body) body?: string | object ### `Optional` headers[](#headers) headers?: Record Overrides RequestOptions.headers ### `Optional` method[](#method) method?: "GET" | "POST" ### `Optional` query[](#query) query?: Record Query params. An object with key-value pair. The object will be serialized as query string and appended to the url. Inherited from RequestOptions.query ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [body](#body) - [headers](#headers) - [method](#method) - [query](#query) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [log](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/functions/handlers.log.html) # Function log - log(arg): void[](#log) - A global function for connector handlers to log information to log file. #### Parameters - ##### arg: unknown #### Returns void ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [Logger](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Logger.html) # Class Logger A logger class for logging connector app messages. - Connector code can utilize the static methods directly without requiring explicit initialization. - All logged messages will be displayed in the browser console and written to the connector's log file. #### Hierarchy - Logger ##### Index ### Methods [debug](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Logger.html#debug) [error](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Logger.html#error) [info](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Logger.html#info) [warn](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.Logger.html#warn) ## Methods ### `Static` debug[](#debug) - debug(message): void[](#debug.debug-1) - Logs a debug message. #### Parameters - ##### message: unknown #### Returns void #### Example ```ts Logger.debug('This is a debug message.'); ``` ### `Static` error[](#error) - error(message): void[](#error.error-1) - Logs an error message. #### Parameters - ##### message: unknown #### Returns void #### Example ```ts Logger.error('This is an error message.'); ``` ### `Static` info[](#info) - info(message): void[](#info.info-1) - Logs an information message. #### Parameters - ##### message: unknown #### Returns void #### Example ```ts Logger.info('This is an information message.'); ``` ### `Static` warn[](#warn) - warn(message): void[](#warn.warn-1) - Logs a warning message. #### Parameters - ##### message: unknown #### Returns void #### Example ```ts Logger.warn('This is a warning message.'); ``` ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [debug](#debug) - [error](#error) - [info](#info) - [warn](#warn) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [Metadata](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.Metadata.html) # Type alias Metadata Metadata: {     name: string;     sourceType: string; } #### Type declaration - ##### name: string - ##### sourceType: string #### Deprecated Will be removed in the later release. ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [NumberFormat](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.NumberFormat.html) # Enumeration NumberFormat The number format for a table column. It can be assigned as metadata for columns of the int and float dataType. ##### Index ### Enumeration Members [Currency](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.NumberFormat.html#Currency) [Number](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.NumberFormat.html#Number) [Percentage](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.NumberFormat.html#Percentage) [Scientific](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.NumberFormat.html#Scientific) ## Enumeration Members ### Currency[](#Currency) Currency: "currency" ### Number[](#Number) Number: "number" ### Percentage[](#Percentage) Percentage: "percentage" ### Scientific[](#Scientific) Scientific: "scientific" ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [Currency](#Currency) - [Number](#Number) - [Percentage](#Percentage) - [Scientific](#Scientific) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [OAuthCredentials](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.OAuthCredentials.html) # Class OAuthCredentials Represents OAuth credentials. includes only access token #### Hierarchy - OAuthCredentials ##### Index ### Constructors [constructor](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.OAuthCredentials.html#constructor) ### Properties [accessToken](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.OAuthCredentials.html#accessToken) ### Accessors [authHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.OAuthCredentials.html#authHeader) ## Constructors ### constructor[](#constructor) - new OAuthCredentials(headers): [OAuthCredentials](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.OAuthCredentials.html)[](#constructor.new_OAuthCredentials) - Create a new instance of OAuthCredentials. #### Parameters - ##### headers: undefined | [SecretsType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.SecretsType.html) The headers containing OAuth secrets. Only `access-token` will be used from the provided headers #### Returns [OAuthCredentials](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/app.OAuthCredentials.html) ## Properties ### `Readonly` accessToken[](#accessToken) accessToken: undefined | string ## Accessors ### authHeader[](#authHeader) - get authHeader(): [AuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.AuthHeader.html) - Get the authentication header based on the access token. #### Returns [AuthHeader](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.AuthHeader.html) The authentication header. ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [constructor](#constructor) - [accessToken](#accessToken) - [authHeader](#authHeader) Generated using [TypeDoc](https://typedoc.org/) **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Package and Sign Your Connector for Distribution  🕐 _6 min read_ Packaging provides a convenient way to distribute your connector as a single `.taco` (Tableau Connector) file. Signing ensures that Tableau loads only `.taco` files that have been signed with a currently valid certificate, ensuring that they haven’t been tampered with. Signing is done using the Java Development Kit (JDK) and a certificate trusted by a root certificate authority (CA) that has been installed in your Java environment. When the certificate expires, Tableau rejects the `.taco` file unless there’s a valid timestamp. Tableau Desktop verifies and loads signed connectors from a standard location (My Tableau Repository\\Connectors) or from a user-supplied directory. This document explains how to package and sign your connector using the TACO Toolkit command-line interface (CLI). ## Before you begin  Be sure you have downloaded the TACO Toolkit. For more information, see [Get Started](https://help.tableau.com/v0.0/api/webdataconnector/en-us/index.html). ## Package the connector To package your connector, run this command: ``` taco pack ``` Your connector is then packaged into a single .taco file. The `taco pack` command packs a taco-built project into a .taco file. This file contains your connector’s runtime artifacts generated from taco build. The `taco pack` command has three stages: - **prepare**: This stage creates the required TACO files according to the information in the connector.json file. - **validate**: This stage verifies that the connector.json and required files are valid. - **pack**: This stage generates the .taco file for your TACO project. After you run the `taco pack` command, you can test the .taco file with Tableau apps and be used for distribution. If you have to customize any XML files for your connector, see the following note. **Note**: If you have to manually customize any XML files (for example, manifest.xml), do the following: 1. Run \`taco pack --prepare\` to generate the XML files based on the settings on the connector.json file. 2. Modify the XML file and then run \`taco pack --validate\` to verify that your added content is valid. If the content is invalid, fix and validate again. 3. After the validation passes, run \`taco pack --skip-prepare\` to skip the initial file generation. ## Sign your packaged connector with jarsigner At this point, your connector is packaged into a single TACO file. Now you must sign the file or disable signature verification to allow it to be loaded automatically into Tableau. ### Why we require connectors to be signed Connectors are sensitive parts of the Tableau code. They handle database authentication and communicate directly with your driver. By signing the connector: - Tableau can verify the authenticity and integrity of the connector. - Customers can be confident that the plugin author is who they say they are. - Customers can know that the TACO file itself hasn’t been tampered with after it was signed. ### Get your connector signed A packaged Tableau connector (.taco) file is functionally the same as a JAR file. Tableau checks that packaged connectors are signed by a trusted certificate authority before loading them and using the default Java keystore in the JRE. Because a TACO file is fundamentally a JAR file, you can follow the [Java documentation for signing JAR files](https://docs.oracle.com/javase/tutorial/deployment/jar/signing.html). **Note**: Certificates are only valid for a certain amount of time, and Tableau doesn’t load connectors with expired certificates. To mitigate this, use a timestamp as described in the following signing example. Timestamps use a timestamp authority to confirm that the certificate was valid when it was signed, even if the certificate is now expired. Also, timestamps are valid for much longer. To sign a TACO file: 1. Generate a certificate signature request (CSR). You can use Java’s [keytool](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html) to generate this CSR. 2. Send the CSR to a certificate authority that is trusted by the Java key store. Make sure that the certificate you get is a code-signing certificate. 3. Sign your TACO file using [jarsigner](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html). 4. Verify that your TACO file is signed using jarsigner as follows: - Use the following command: `jarsigner -verify path_to_taco -verbose -certs -strict` If “jar verified” appears, your TACO file is ready to be used in Tableau. - Double-check the certificate chain to make sure that the final certificate is from your certificate authority. - Take note of when the TACO file expires. After it does, users will no longer be able to use the connector in Tableau without disabling verification and you must provide a new signed TACO file. ### Signing example Getting a certificate is a multi-step process. This example illustrates how to sign a TACO file with a basic signed certificate. #### Step 1: Generate a Certificate Signing Request (CSR) file A certificate signing request (CSR) is a request for a certificate authority (CA) to create a public certificate for your organization. 1. Generate a key pair using this command: `keytool -genkeypair -alias your_alias -keystore your_keystore` 2. Export the key to a certificate file: `keytool -export -alias your_alias -file cert_file -keystore your_keystore` 3. Now you can generate your certificate signing request: `keytool -certreq -alias your_alias -keystore your_keystore -file certreq_file` Keep all files you’ve generated (the key pair, the keystore, and the csr) secure. You’ll need them later. For more information about keytool arguments, see the Java Documentation about [keytool](https://docs.oracle.com/javase/8/docs/technotes/tools/unix/keytool.html) on the Oracle website. #### Step 2: Get the CSR signed by the certificate authority Send the certificate signing request to the CA you want to create a certificate for you (for example, Verisign or Thawte). The CA signs the CSR file with their own signature and send that certificate back to you. You can then use this signed certificate to sign the TACO file. After you receive/fetch the new certificate from the CA, along with any applicable “chain” or intermediate certificates, run the following command to install the new certificate and chain into the keystore: `keytool -importcert cert_from_ca -keystore your_keystore` #### Step 3: Use jarsigner to sign the TACO file Using the keystore you imported your signed certificate to, use jarsigner to sign your TACO file: `jarsigner -keystore your_keystore path_to_taco your_alias -tsa url` The `-tsa url` argument is optional, but we recommend that you use it. It’s the URL to a Timestamp Authority. By adding this argument, you stamp the signed TACO file with a timestamp, extending its period of validity. While there are several free options for timestamp authority, the CA you got the certificate from will most likely have a timestamp authority you can use. For more information about jarsigner arguments, see the Java Documentation about [jarsigner](https://docs.oracle.com/javase/8/docs/technotes/tools/windows/jarsigner.html). **Note**: Earlier versions of the packager signed your connector using jarsigner internally. This functionality was removed in favor of the connector author calling jarsigner directly, which provides more control over how your connector is signed. ## More information For more information about web data connectors, see [Connectors Built with the Web Data Connector 3.0 SDK](https://help.tableau.com/current/pro/desktop/en-us/examples_wdc_connector_sdk.htm). - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [ParquetUtils](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.ParquetUtils.html) # Class ParquetUtils #### Hierarchy - ParquetUtils ##### Index ### Properties [parse](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.ParquetUtils.html#parse) ## Properties ### `Static` parse[](#parse) parse: ((data, tableName) => Promise<[DataTable](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html)\>) #### Type declaration - - (data, tableName): Promise<[DataTable](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html)\> - A utility method to parse Parquet data into a [DataTable](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html) object. This function returns a Promise that resolves to a DataTable object. #### Parameters - ##### data: Uint8Array - ##### tableName: string #### Returns Promise<[DataTable](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataTable.html)\> #### Example ```ts import { ParquetUtils } from '@tableau/taco-toolkit/handlers' export default class MyParser extends Parser { parse(data: Uint8Array, options: ParseOptions): DataContainer { const result = await ParquetUtils.parse(data, 'tablename') // result: a DataTable object } } ``` ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [parse](#parse) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [ParseOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.ParseOptions.html) # Interface ParseOptions #### Hierarchy - ParseOptions ##### Index ### Properties [dataContainer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.ParseOptions.html#dataContainer) [handlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.ParseOptions.html#handlerInput) ## Properties ### dataContainer[](#dataContainer) dataContainer: [DataContainer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataContainer.html) ### handlerInput[](#handlerInput) handlerInput: [HandlerInput](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.HandlerInput.html) ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [dataContainer](#dataContainer) - [handlerInput](#handlerInput) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [Parser](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Parser.html) # Class Parser`Abstract` An abstract class for the implementation of connector custom parsing that synchronously parses the results yielded from the Fetcher. For TypeScript, the fetcherResult type can be provided via the type parameter. By default, fetcherResult is typed as `any`. #### Example ```ts export default class MyParser extends Parser { parse(fetcherResult: Uint8Array, options: ParseOptions): DataContainer { // ... }} ``` #### Type Parameters - #### FetchResult = any #### Hierarchy - BaseParser - Parser ##### Index ### Constructors [constructor](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Parser.html#constructor) ### Methods [parse](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Parser.html#parse) [createContainerBuilder](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Parser.html#createContainerBuilder) ## Constructors ### constructor[](#constructor) - new Parser(): [Parser](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Parser.html)[](#constructor.new_Parser) - #### Type Parameters - #### FetchResult = any #### Returns [Parser](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.Parser.html) Inherited from BaseParser.constructor ## Methods ### `Abstract` parse[](#parse) - parse(fetcherResult, options): [DataContainer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataContainer.html)[](#parse.parse-1) - The method to implement the parsing logic for transforming the fetcherResult into a DataContainer. When a custom parser is defined, the connector must implement this method to perform data parsing. #### Parameters - ##### fetcherResult: FetchResult - ##### options: [ParseOptions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.ParseOptions.html) #### Returns [DataContainer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataContainer.html) ### `Static` createContainerBuilder[](#createContainerBuilder) - createContainerBuilder(dataContainer): [DataContainerBuilder](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataContainerBuilder.html)[](#createContainerBuilder.createContainerBuilder-1) - A static method to create a DataContainerBuilder instance based on the provided dataContainer object. #### Parameters - ##### dataContainer: [DataContainer](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/interfaces/handlers.DataContainer.html) #### Returns [DataContainerBuilder](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/classes/handlers.DataContainerBuilder.html) Inherited from BaseParser.createContainerBuilder ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [constructor](#constructor) - [parse](#parse) - [createContainerBuilder](#createContainerBuilder) Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [SecretsType](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/app.SecretsType.html) # Type alias SecretsType SecretsType: Record Represents a collection of secrets with string keys and values. #### Example ```ts const secrets: SecretsType = { accessToken: 'access_Token', refreshToken: 'refresh_Token', // other secrets...}// Usage to retrieve a secret valueconst { accessToken, refreshToken } = secrets ``` ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Supported Date Formats 🕐 _1 min read_ Web data connectors can work with Date and DateTime values that use the following formats: ``` dd-MM-yyyy dd-MMM dd-MMM-yy dd-MMM-yyyy dd-MMM-yyyy HH:mm:ss dd/MM/yyyy h:mm a HH.mm hh.mm a HH.mm.ss hh.mm.ss a hh:mm a HH:mm:ss hh:mma M/d/yyyy HH:mm:ss MM-dd-yyyy MM-dd-yyyy HH:mm MM/dd/yy MM/dd/yy HH:mm:ss MM/dd/yyyy MM/dd/yyyy MM/dd/yyyy HH:mm:ss MM/dd/yyyy hh:mm:ss a MMM yyyy MMM-yy MMMM dd yyyy MMMM dd yyyy hh:mma MMMM dd, yyyy MMMM dd, yyyy HH:mm:ss MMMM dd,yyyy MMMM dd,yyyy HH:mm:ss yyyy-MM-dd yyyy-MM-dd HH:mm yyyy-MM-dd HH:mm:ss yyyy-MM-dd HH:mm:ss.SSS yyyy-MM-dd HH:mm:ss.SSS yyyy-MM-dd HH:mm:ss.SSS yyyy/MM/dd yyyy/MM/dd HH:mm:ss ``` For information about the symbols used in these format examples, see [Formatting Dates and Times](http://userguide.icu-project.org/formatparse/datetime) on the ICU User Guide site. **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # TACO Toolkit Reference 🕐 _4 min read_ This topic contains information to help you understand the TACO Toolkit and its associated command-line interface (CLI). ## Overview The TACO Toolkit is a set of tools that helps simplify Tableau web data connector development. It contains a command-line interface (CLI) to create and publish Tableau web data connectors and a software development kit (SDK) that enables you to develop your connectors efficiently. - The TACO CLI provides a global way to create and build a TACO project that contains your connector source code. The CLI can also pack a built TACO project into a Tableau TACO connector (the .taco file). - The TACO SDK provides application programming interfaces (APIs) to help you develop your TACO projects (the source code). The SDK also provides some npm scripts, which allow you to build and test your projects with the standard npm commands. - The EPS is started by the TACO CLI or the npm scripts to load and test your connector source code. ## Prerequisites The TACO Toolkit requires that you have the following installed on your machine: - [Java 8 or above](https://www.oracle.com/java/technologies/javase-downloads.html) - [Python 3.x](https://www.python.org/downloads/) ## TACO development scripts (`taco-scripts`) The TACO Toolkit project has standard npm support for development. It provides three npm scripts from the local taco-toolkit dependency. ``` // connector/package.json "scripts": { "build": "taco-script build", "clean": "taco-script clean", "start": "taco-script start" } ``` You can use npm commands under the `/connector` directory for local development without worrying about the global taco CLI version. ``` npm run build npm run clean npm start ``` ### `taco-scripts build` The `build` script generates the runtime artifacts of a connector, including the JS bundle of app and handlers, and connector.json, which contains the connector configurations. ### `taco-scripts clean` The `clean` script removes all artifacts generated from build. ### `taco-scripts start` The `start` script starts an EPS server and loads the connector from the built taco project. You can use this script for testing a connector during local development. **Note**: The EPS server doesn’t consume any TACO infrastructure files. It's only used for testing the EPS connector logic. ## TACO global commands (`taco-cli`) ### `taco create` `taco create` creates a TACO project with a boilerplate type option. You can use the boilerplate TACO project as the starter to develop your own TACO connector. **Usage:** ``` taco create --boilerplate earthquake-data ``` `taco create` also provides git support. The command can initialize a taco project a git repo when `--git` option is present. ``` taco create --boilerplate earthquake-data --git ``` ### `taco build` `taco build` is a wrapper of `taco-scripts build`, which allows you to run build at the root level of a TACO project. `taco build` also provides a `--clean` option that removes all existing artifacts in the project and reinstalls dependency packages before performing the build. ```Bash taco build --clean ``` ### `taco clean` `taco clean` is a wrapper of `taco-scripts clean`, which allows developers to run clean at the root level of a TACO project. By default, `taco clean` only removes the artifacts related to EPS connector. It also provides a few options to clean other generated sources. ``` --include-optional remove the optional taco infrastructure files (e.g. manifest.xml) --include-log remove taco CLI log files --all remove all generated taco files and directories ``` ### `taco start` `taco start` is a wrapper of `taco-scripts start`, which allows developers to run build at the root level of a taco project. ### `taco pack` `taco pack` packs a taco-built project into a `.taco` file, which contains a connector’s runtime artifacts generated from the `taco build` command. The `.taco` file can be tested with Tableau apps and be used for distribution. **Usage:** ``` cd taco-project taco pack ``` `taco pack` have 3 stages: - **prepare**: create the required TACO files according to the information in connector.json - **validation**: validate connector.json and required files - **pack**: generate `.taco` file for the given TACO project To perform a single stage operation, you can use the corresponding flag: ``` taco pack --prepare // only perform prepare stage taco pack --validate // only perform validation stage ``` You may also skip the **prepare** stage with `--skip-prepare`, when you have any manual modification on the taco files. ### `taco run` `taco run` launches a Tableau app with loading the taco connector(s) under a certain directory. The target taco connector has to be built and packed. The default taco directory is the current working directory. ``` taco run Desktop --version near taco run Desktop --version 2022.3 --taco-dir 'path/to/taco/dir' ``` You can also specify a Tableau app’s executable file path with `--app-path`. When `--app-path` is provided, the `tableau-app-name` argument and `--version` option will be ignored. ``` taco run --app-path '/Applications/Tableau Desktop near.app' --taco-dir 'path/to/taco/dir' ``` ### `taco unpack` The `unpack` command unpacks the `.taco` file into the current directory. It unzips the taco file. ``` taco unpack earthquake-data.taco ``` The `unpack` command unpacks the `earthquake-data.taco` into the `earthquake-data` directory in the command’s current working directory. The command returns an Error if there’s already an `earthquake-data` directory. - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [handlers](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/handlers.html) - [TacoFileParserName](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/types/handlers.TacoFileParserName.html) # Type alias TacoFileParserName TacoFileParserName: "taco:excel-file-parser" | "taco:csv-file-parser" | "taco:parquet-file-parser" | "taco:data-file-parser" Represents the name of a built-in Taco file parser. #### Example ```ts const parserName: TacoFileParserName = 'taco:csv-file-parser'; ``` ### Settings #### Member Visibility - Inherited #### Theme OSLightDark Generated using [TypeDoc](https://typedoc.org/) - [@tableau/taco-toolkit](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) - [app](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/modules/app.html) - [UnitsFormat](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.UnitsFormat.html) # Enumeration UnitsFormat The unit format for a table column. It can be assigned as metadata for columns of the int and float dataType. ##### Index ### Enumeration Members [BillionsEnglish](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.UnitsFormat.html#BillionsEnglish) [BillionsStandard](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.UnitsFormat.html#BillionsStandard) [Millions](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.UnitsFormat.html#Millions) [Thousands](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/enums/app.UnitsFormat.html#Thousands) ## Enumeration Members ### BillionsEnglish[](#BillionsEnglish) BillionsEnglish: "billions\_english" ### BillionsStandard[](#BillionsStandard) BillionsStandard: "billions\_standard" ### Millions[](#Millions) Millions: "millions" ### Thousands[](#Thousands) Thousands: "thousands" ### Settings #### Member Visibility - Inherited #### Theme OSLightDark ### On This Page - [BillionsEnglish](#BillionsEnglish) - [BillionsStandard](#BillionsStandard) - [Millions](#Millions) - [Thousands](#Thousands) Generated using [TypeDoc](https://typedoc.org/) **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Use a WDC in Tableau Server You can use your web data connector (WDC) on Tableau Server as you would any other data source. You can publish the web data connector as a data source, or you can publish a workbook that embeds your connector as the data source. When you use a web data connector, Tableau creates an extract of the data. You can refresh the extract in Tableau Desktop. However, to be able to refresh the extract on Tableau Server, there are a couple of other considerations. - If your web data connector requires authentication, you need to embed the credentials when you publish the data source or workbook. This is because the refresh can occur on a schedule or in some other background context, and the server cannot prompt for credentials. You should store credentials in `tableau.username` and `tableau.password` as these fields are encrypted. Do not use `tableau.connectionData` for sensitive information as this field is stored in plain text. - You need to ensure that your web data connector is added to the safe list, and also ensure that the secondary safe list includes the domains that the connector can send requests to and receive requests from (external JavaScript libraries, local files, REST APIs). Because a WDC contains JavaScript and typically connects to other sites, you need to work with the Tableau Server administrator to test and verify the connector is safe to use. After verifying the WDC, the Tableau Server administrator can use the Tableau Services Manager (TSM) command line interface (CLI) to allow the WDC on the Tableau Server. For example, a Tableau Server administrator might use the following TSM command to add the sample USGS EarthQuake data connector to the safe list. This command also adds a secondary safe list that includes the domains of the libraries and sources that the WDC makes use of. You can’t use wildcards in the primary URL (`--url`), but you can use wildcards (`.*`) in the secondary safe list (`--secondary`). ``` tsm data-access web-data-connectors add --name "USGS Earthquakes" --url https://tableau.github.io:443/webdataconnector/Examples/html/earthquakeUSGS.html --secondary https://tableau.github.io/.*,https://earthquake.usgs.gov/.*,https://maxcdn.bootstrapcdn.com/.*,https://ajax.googleapis.com/.*,https://connectors.tableau.com/.* ``` - For security, consider using HTTPS protocol for the connector and all external libraries that your web data connector uses. For more information, see [Web Data Connectors in Tableau Server](http://onlinehelp.tableau.com/current/server/en-us/datasource_wdc.htm) and [Testing and Vetting Web Data Connectors](http://onlinehelp.tableau.com/current/server/en-us/datasource_wdc_vetting.htm) in the Tableau Server Help. **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # WDC Incremental Refresh Tableau uses web data connectors to fetch data and store that data in an extract. You can always refresh the entire extract. However, if you implement incremental refresh, you can also fetch only the new data for the extract, which can greatly reduce the time required to download the data. It’s possible to enable incremental refresh functionality for any table that is brought back by the web data connector. To enable incremental refresh functionality on a table, you must set the [tableInfo.incrementColumnId](/v0.0/api/webdataconnector/en-us/docs/api_ref#webdataconnectorapi.tableinfo-1.incrementcolumnid) property on the tableInfo object for that table as defined in your [getSchema](/v0.0/api/webdataconnector/en-us/docs/api_ref#webdataconnectorapi.webdataconnector.getschema) function. The incrementColumnId property should be set to the ID of the column that will be used as the key for the incremental refresh. For example, suppose you had a table with an ID field. For every new record in the table, the ID is incremented by 1, and no previous data is ever deleted or overwritten. In that scenario, you would want the ID column to be referenced by incrementColumnID. That way, when gathering data, you can fetch only the records that have an ID that’s larger than the largest ID you’ve fetched during the last gather data phase. For example, here’s the getSchema method of the IncrementalRefreshConnector dev sample: ``` myConnector.getSchema = function(schemaCallback) { var cols = [ { id: "id", dataType: tableau.dataTypeEnum.int }, { id: "x", dataType: tableau.dataTypeEnum.string }, { id: "day", dataType: tableau.dataTypeEnum.datetime }, { id: "day_and_time", dataType: tableau.dataTypeEnum.datetime }, { id: "true_or_false", dataType: tableau.dataTypeEnum.bool }, { id: "color", dataType: tableau.dataTypeEnum.string } ]; var tableInfo = { alias: "Incremental Refresh Connector", id: "mainTable", columns: cols, incrementColumnId: "id" }; schemaCallback([tableInfo]); }; ``` When Tableau calls the getData method of the connector, it passes in a table object. If an incremental refresh is being requested by the end user in Tableau, and if the [tableInfo.incrementColumnId](/v0.0/api/webdataconnector/en-us/docs/api_ref#webdataconnectorapi.tableinfo-1.incrementcolumnid) was set during the getSchema function for that table, then the table object will contain a value in the [table.incrementValue](/v0.0/api/webdataconnector/en-us/docs/api_ref#webdataconnectorapi.table.incrementvalue) property. This value will contain the current largest value from the increment column. For example, this is how this property is used in the IncrementalRefreshConnector dev sample: ``` myConnector.getData = function(table, doneCallback) { var lastId = parseInt(table.incrementValue || -1); // Gather only the most recent data with an ID greater than 'lastId' // ...... table.appendRows(dataArray); doneCallback(); }; ``` The WDC API supports three data types for the incremental refresh column: DateTime, Date, and integer. For incremental refresh, you typically use a field that represents a date, a timestamp, or a row number. **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # WDC Lifecycle and Phases 🕐 _2 min read_ This topic explains the overall lifecycle of a Tableau Web Data Connector (WDC). We recommend that you understand the content in the [Get Started](/v0.0/api/webdataconnector/en-us/index.html) topic before diving into this topic. A WDC is always run with an associated phase. Tableau loads the connector inside a web browser at different times and in distinct phases. This topic explains each of these phases. ## Interactive phase: Interact with the user In the interactive phase, Tableau launches the connector UI. This is the connector’s UI. During the interactive phase, the following actions happen: 1. **Initialize**: The connector is executed `new Connector(onInitialized)`. 2. **Get user input**: After it’s ready, the connector allows connector-specific input.The connector waits for interaction to be completed by the user. This could be waiting for the user to enter data in a form, waiting for the user to authenticate (for non-OAuth connectors—OAuth happens before the interactive phase), and more. This is optional, if a connector has no need for user input, it can call `connector.submit()` immediately. 3. **Pass the data**: The user data is then passed to the connector in `connector.handlerInputs`. Secrets are passed as an object to `connector.secrets`. 4. **Submit**: The connector calls the function `connector.submit()` to finish the interactive phase. ## Data gathering phase: Fetch data from data source After the interactive phase has been completed, the connector sends the user data to EPS, which triggers the data gathering phase. In the data gathering phase, the following steps take place: 1. **Authenticate** (optional): If your connector requires authentication, the pipeline runs the authenticator in the handlers. 2. **Retrieve the data**: The fetcher handler retrieves the data from the connector’s data source, according to how and where you have defined it to fetch your data. (data transportation) The result of the fetch API is passed to the parser handler. 3. **Transform the data**: The parser handler maps the data to Tableau tables. **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # WDC Node.js Proxy with OAuth Tutorial ## This tutorial builds on what you learned about web data connectors in the [Basic tutorial](/v0.0/api/webdataconnector/en-us/docs/wdc_tutorial.html). Ensure that you understand the concepts in the basic tutorial before you continue. By the end of this tutorial, you’ll have a working WDC that connects to [Foursquare](https://foursquare.com) and downloads data for sites that you “liked” in Foursquare. This is a multi-step tutorial on how to use OAuth with a Tableau web data connector. Here is a list of all the steps: 1. [Introduction and Overview](/v0.0/api/webdataconnector/en-us/docs/wdc_oauth_tutorial.html#step-1-introduction-and-overview) 2. [Create a Foursquare App](/v0.0/api/webdataconnector/en-us/docs/wdc_oauth_tutorial.html#step-2-create-a-foursquare-app) 3. [Install and configure the web server](/v0.0/api/webdataconnector/en-us/docs/wdc_oauth_tutorial.html#step-3-install-and-configure-the-web-server) 4. [Create the UI for Signing In](/v0.0/api/webdataconnector/en-us/docs/wdc_oauth_tutorial.html#step-4-create-the-ui-for-signing-in) 5. [Add Code for OAuth Sign-In](/v0.0/api/webdataconnector/en-us/docs/wdc_oauth_tutorial.html#step-5-add-code-for-oauth-sign-in) 6. [Test OAuth Sign-In](/v0.0/api/webdataconnector/en-us/docs/wdc_oauth_tutorial.html#step-6-test-oauth-sign-in) 7. [Get Columns and Data](/v0.0/api/webdataconnector/en-us/docs/wdc_oauth_tutorial.html#step-7-get-columns-and-data) 8. [Manage Credentials](/v0.0/api/webdataconnector/en-us/docs/wdc_oauth_tutorial.html#step-8-manage-credentials) 9. [Test the Connector in the Simulator](/v0.0/api/webdataconnector/en-us/docs/wdc_oauth_tutorial.html#step-9-test-the-connector-in-the-simulator) 10. [Test the Connector in Tableau](/v0.0/api/webdataconnector/en-us/docs/wdc_oauth_tutorial.html#step-10-test-the-connector-in-tableau) **Note**: To see all the code for the tutorial, see [Complete Code Listing](/v0.0/api/webdataconnector/en-us/docs/wdc_oauth_tutorial.html#complete-code-listing). * * * # Step 1 Introduction and Overview In this part of the tutorial, you’ll learn these things: - [The tutorial scenario](#tutorial-scenario). This section describes the web data connector that you’ll build. - [Prerequisites](#prerequisites). What you’ll need, and what we assume you already know about web data connectors. - [What is OAuth?](#what-is-oath) If you’re new to OAuth, this section provides a quick overview. - [Which OAuth grant should I use?](#client-and-server-flow) There are two basic ways to work with OAuth: One uses the implicit grant and client-side flow, and the other uses the authorization code grant and server-side flow. This section provides a brief overview of each and when to use them. ## The tutorial scenario If you _really_ want to skip all of this and go straight to the source code, look for the `foursquare` files in the `Examples\OAuthProxyExample` directory. However, you’ll get a lot more out of this if you build it yourself following along with this tutorial. **Note**: The connector that we’ll create in this tutorial (`foursquareWDC`) has a different name than the same connector in the `Examples\OAuthProxyExample` directory (`foursquare`). This is to minimize the chances of overwriting the existing sample. In this tutorial, you copy some of the files over from the existing sample. These are files that you need to set up the web server. You can adapt this process to create and test new connectors that also require OAuth support. In this tutorial, you’ll build a web data connector that gets data from Foursquare ([http://foursquare.com](http://foursquare.com)). Foursquare is an app that allows users to search for local services, such as restaurants or attractions. Foursquare also exposes an API that developers can use to perform many of the functions that the app has. Foursquare is one of many sites that use OAuth with their APIs. Others are Facebook, Yelp, Tumblr, Twitter, Spotify, Etsy, and many more. For this tutorial, you’ll create a web data connector that calls the Foursquare [`venuelikes`](https://developer.foursquare.com/docs/users/venuelikes) endpoint, which returns a list of venues that a specific user has “Liked” in Foursquare. When you call the `venuelikes` endpoint, you must include an OAuth access token. The token tells Foursquare that the user has allowed your app—namely, the web data connector—to access the user’s personal information on Foursquare. **Note**: This tutorial illustrates how to use [OAuth 2.0](http://oauth.net/2/). ## Prerequisites To run this tutorial, you need the following: 1. Basic familiarity with JavaScript. 2. The Web Data Connector SDK installed on your computer. 3. Familiarity with the concepts and web data connector example in the [Basic tutorial](/v0.0/api/webdataconnector/en-us/docs/wdc_tutorial.html). 4. A web server running locally on your computer and listening on port 3333. In this tutorial, you will use [Node.js](https://nodjs.org) and [Express](https://expressjs.org) framework to create a simple web server that will handle the server-side authentication. You can adapt this model to create and test new connectors. We will cover installing and configuring the web server in this tutorial. ## What is OAuth and how does it work? This section provides some basic information about OAuth for those who are not familiar with it. OAuth is an authentication protocol that allows an _application_ (in our case, a web data connector) to request specific resources from a _resource provider_ (Foursquare) on behalf of a specific _resource owner_ (the user who signs in to Foursquare). This is a more secure and usable alternative to the application asking the user directly for their Foursquare username and password. To use OAuth, an application must be registered with the OAuth resource provider. For example, in this tutorial, you register your application with Foursquare. (If you were using a different OAuth provider, you would register your application with that provider.) The provider assigns a _client ID_ to identify the application and a _client secret_ that is known only by the application and the OAuth provider and is used to authorize the application to make requests on behalf of the user. When the application contacts the OAuth provider, the application passes the client ID to identify itself. The exact process for registering your application differs for each provider, and is typically explained in the provider’s documentation for how to use their API. The following diagram illustrates an example OAuth flow, which is the flow you will build. The steps following the diagram describe the steps in the flow. ![](/v0.0/api/webdataconnector/en-us/assets/wdc_tutorial_oauth_flow-3.png) 1. To connect to data, the end user loads the web data connector in Tableau. 2. The connector displays a button that prompts the user to go to Foursquare to sign in. When the user clicks the button, the connector redirects the user to Foursquare to sign in. (The redirect URL includes the client ID for your connector.) 3. On the Foursquare site, the user signs in and grants permission to the connector to access the user’s personal information. 4. Foursquare redirects the user back to the connector. As part of the URL that redirects the user back to the connector, Foursquare includes an authorization code. 5. The HTTP server we setup with Node.js Express accepts the authorization code and issues a request to Foursquare for an access token. The request includes the client ID and the client secret, a unique identifier that only the server and the Foursquare OAuth provider have knowledge of. The client secret is to ensure that some other application can’t impersonate your connector. 6. Foursquare verifies the authorization code and client secret and returns an access token. 7. The connector includes the access token when it makes requests to Foursquare endpoints. When Foursquare gets the requests, it recognizes that the call is on behalf of the user. 8. Foursquare returns the requested information for the user represented by the access token. ## Which OAuth grant type should I use? Applications can use OAuth using one of several grant types. A grant type refers to the way an application goes about getting an access token after a user has authorized the application. Two common ones and the ones described here are the authorization code grant and the implicit grant. The grant type you choose determines the type of authorization flow you use. With the authorization code grant, the application requests an authorization code when the user signs in, which is then exchanged for an access token. The authorization code grant can be referred to as server-side flow, as the authorization flow goes through the application’s back end (or server-side) code, which handles exchanging the authorization code and the client secret for the access token. When you use the implicit grant, the application requests the access token, which is returned when the user gives the application permission. This type of grant could be referred to as client-side flow, as the JavaScript that runs in the browser makes the OAuth calls and handles the access token. The primary motivation for using authorization code grant and the server-side flow is to increase security. In client-side flow, all the information required in order to get an access token is on the client—that is, in JavaScript code. This makes the information visible to anyone who can read that JavaScript code. In the server-side flow, the server keeps the client secret that’s assigned to the app, and the secret is used to get the access token. Which should you use? A rule of thumb is that if you’re calling endpoints that require your client secret, you should use the authorization code grant and the server-side flow. The client secret should be kept secure, and the implicit grant and client-side flow potentially exposes the secret. In the server-side flow, the client secret can be kept more secure on the server. We use the authorization code grant and server-side flow in this tutorial. However, if you’re not calling endpoints that require the client secret, it’s generally easier to implement the client-side flow. * * * # Step 2 Create a Foursquare App [(Back to top)](#top) In this part of the tutorial, you’ll create an account with Foursquare (the OAuth provider) and register your app. You’ll get back a client ID and client secret that you’ll need for making calls to Foursquare later. ## Register your app with Foursquare Before you create the web data connector, you must register your Foursquare application (the web data connector) on the Foursquare developer site. When you’re done, you’ll have a client ID that you use when you communicate with Foursquare and that lets Foursquare know who is making requests. 1. Go to the [Foursquare.com](https://foursquare.com/) site. If you have a Foursquare developer account, sign in. Otherwise, sign up for a new account. 2. Go to the [My Apps](https://foursquare.com/developers/apps) page (https://foursquare.com/developers/apps) on the Foursquare developer website.{:target=”\_blank”} 3. Click the **Create a new app** button. 4. Fill in the **Your app name**, **Download/welcome page url**, and **Redirect URI(s)** boxes. You can use any values you want for the application name and welcome page URL. For the **Redirect URI** box, enter the following: `http://localhost:3333/redirect` You will use this value later on when you make a call to the Foursquare OAuth service. 5. Click **Save Changes**. Foursquare displays a client ID and a client secret. 6. Copy the client ID and client secret and keep them in a secure location. **Note**: For this tutorial, you need the client ID and the client secret. The client ID is used for the initial request for authorization. The client secret is used by the local web server to complete the authorization and to obtain the access token. The client secret must be kept secure and away from public view. In this tutorial, we use the client secret on our web server and not in our Foursquare WDC application, where the JavaScript code is potentially accessible. ## “Like” some venues If you’re new to Foursquare, you don’t have any “Liked” venues. To make sure you have some data to work with later, do this. 1. Go to the [Foursquare.com](https://www.foursquare.com) site and sign in. 2. Go to the [City Guide](https://foursquare.com/city-guide), and search for venues and display the listing for a venue that you like. 3. Click the “Like” icon for the venue near the top of the listing. ![](/v0.0/api/webdataconnector/en-us/assets/wdc_tutorial_oauth_foursquare_likes2.png) 4. Repeat steps 2 and 3 a few times until you have a selection of “Liked” venues to test later. **Next** In the next part of the tutorial, you’ll create the folders on your computer where you will host the connector and you will configure the Node.js web server. * * * # Step 3 Install and configure the web server [(Back to top)](#top) In this part of the tutorial, you will create a new directory for your web data connector. You will also copy the Node.js files over from the `Examples\OAuthProxyExample`directory and then configure the web server to handle the server side OAuth flow, using the client id and client secret you obtained from Foursquare. 1. Create a directory for this foursquare web data connector under the `Examples` folder (for example, `Examples\FoursquareWDC`). 2. Copy the following files: `app.js`, `config.js`, and `package.json` from the `Examples\OAuthProxyExample` folder to the folder you just created in step 1. 3. After you copy the three files, create a new folder in your directory called `public`. You will use this folder later for your connector’s public-facing web page (for example, `Examples\FoursquareWDC\public`). 4. Open a Command or shell window and navigate to the directory where you copied the files (`Examples\FoursquareWDC`). Install the express server with the following the following command: **npm install** The command will install all the files you need to run the web server. 5. Configure the web server. Edit the `config.js` file in the directory you created and add information about your app. Use **http://localhost** for the `HOSTPATH` and the **3333** as the `PORT`. The `REDIRECT_PATH` should be **/redirect**. Your file should look like the following. Replace `YOUR_CLIENT_ID` and `YOUR CLIENT_SECRET` with the actual values from Foursquare you saved earlier when you registered your app. ``` // The necessary configuration for your server // Contains credentials for your Foursquare application // And the new redirect path for the OAuth flow module.exports = { 'HOSTPATH': 'http://localhost', 'PORT': 3333, 'CLIENT_ID': 'YOUR_CLIENT_ID', 'CLIENT_SECRET': 'YOUR_CLIENT_SECRET', 'REDIRECT_PATH': '/redirect' }; ``` The information you entered in the `config.js` file will be used to get the access token from Foursquare. The authorization flow is handled in the web server that you configured, so that the client secret is inaccessible from the public facing web pages that you will create in the next step. * * * # Step 4 Create the UI for Signing In [(Back to top)](#top) In this part of the tutorial, you create an HTML page that contains markup for the UI that lets the user sign in to Foursquare. The HTML page renders the following: ![](/v0.0/api/webdataconnector/en-us/assets/wdc_tutorial_oauth_basic_signin_ui.png) You also add JavaScript code that toggles text in the page (“You are signed in” or “You are not signed in”), depending on whether the user is signed in. ## Get the button graphic The page we are creating uses a graphic for the **Connect to Foursquare** button. - Copy the `foursquare_connect.png` file from the `Examples\OAuthProxyExample\public` folder and place it in the folder we created for our web page: `Examples\FoursquareWDC\public`. ![](/v0.0/api/webdataconnector/en-us/assets/foursquare_connect.png) If you create a web data connector for a service that uses OAuth or another authorization method, it is best to use the official buttons and logos from the service. Follow whatever guidance the service recommends regarding the use of trademarks and resources, such as buttons and icons. For this tutorial, we downloaded the graphic from the Foursquare resources page: `https://foursquare.com/about/logos`. Note that the Foursquare UI for downloading assets might change without notice. ## Create the HTML markup 1. Create a new file named `index.html` in the `Examples\FoursquareWDC\public` folder. Then copy the following markup into the new file. ``` Foursquare Connector

You are signed in!

You are not signed in, please click below to sign in to your Foursquare account.

Login with Foursquare

Get Venues I Like

``` At the top of the file, there are `

You are signed in!

You are not signed in, please click below to sign in to your Foursquare account.

Login with Foursquare

Get Venues I Like

``` ## FoursquareWDC.js ``` (function() { 'use strict'; // This config stores the important strings needed to // connect to the foursquare API and OAuth service to // gain authorization that we then exchange for an access // token. // // Do not store your client secret here. // We are using a server-side OAuth flow, and the client // secret is kept on the web server. var config = { clientId: 'YOUR_CLIENT_ID', redirectUri: 'http://localhost:3333/redirect', authUrl: 'https://foursquare.com/', version: '20190102' }; // more code goes here // This function parses the access token in the URI if available // It also adds a link to the foursquare connect button $(document).ready(function() { var accessToken = Cookies.get("accessToken"); var hasAuth = accessToken && accessToken.length > 0; updateUIWithAuthState(hasAuth); $("#connectbutton").click(function() { doAuthRedirect(); }); $("#getvenuesbutton").click(function() { tableau.connectionName = "Foursquare Venues Data"; tableau.submit(); }); }); // An on-click function for the connect to foursquare button, // This will redirect the user to a foursquare login function doAuthRedirect() { var appId = config.clientId; if (tableau.authPurpose === tableau.authPurposeEnum.ephemerel) { appId = config.clientId; // This should be Desktop } else if (tableau.authPurpose === tableau.authPurposeEnum.enduring) { appId = config.clientId; // This should be the Tableau Server appID } var url = config.authUrl + 'oauth2/authenticate?response_type=code&client_id=' + appId + '&redirect_uri=' + config.redirectUri; window.location.href = url; } //------------- OAuth Helpers -------------// // This helper function returns the URI for the venueLikes endpoint // It appends the passed in accessToken to the call to personalize the call for the user function getVenueLikesURI(accessToken) { return "https://api.foursquare.com/v2/users/self/venuelikes?oauth_token=" + accessToken + "&v=" + config.version; } // This function toggles the label shown depending // on whether or not the user has been authenticated function updateUIWithAuthState(hasAuth) { if (hasAuth) { $(".notsignedin").css('display', 'none'); $(".signedin").css('display', 'block'); } else { $(".notsignedin").css('display', 'block'); $(".signedin").css('display', 'none'); } } //------------- Tableau WDC code -------------// // Create tableau connector, should be called first var myConnector = tableau.makeConnector(); // Init function for connector, called during every phase but // only called when running inside the simulator or tableau myConnector.init = function(initCallback) { tableau.authType = tableau.authTypeEnum.custom; // If we are in the auth phase we only want to show the UI needed for auth if (tableau.phase == tableau.phaseEnum.authPhase) { $("#getvenuesbutton").css('display', 'none'); } if (tableau.phase == tableau.phaseEnum.gatherDataPhase) { // If API that WDC is using has an endpoint that checks // the validity of an access token, that could be used here. // Then the WDC can call tableau.abortForAuth if that access token // is invalid. } var accessToken = Cookies.get("accessToken"); console.log("Access token is '" + accessToken + "'"); var hasAuth = (accessToken && accessToken.length > 0) || tableau.password.length > 0; updateUIWithAuthState(hasAuth); initCallback(); // If we are not in the data gathering phase, we want to store the token // This allows us to access the token in the data gathering phase if (tableau.phase == tableau.phaseEnum.interactivePhase || tableau.phase == tableau.phaseEnum.authPhase) { if (hasAuth) { tableau.password = accessToken; if (tableau.phase == tableau.phaseEnum.authPhase) { // Auto-submit here if we are in the auth phase tableau.submit() } return; } } }; // Declare the data to Tableau that we are returning from Foursquare myConnector.getSchema = function(schemaCallback) { var schema = []; var col1 = { id: "Name", dataType: "string"}; var col2 = { id: "Latitude", dataType: "float"}; var col3 = { id: "Longitude", dataType: "float"}; var col4 = { id: "Address", dataType: "string"}; var cols = [col1, col2, col3, col4]; var tableInfo = { id: "FoursquareTable", columns: cols } schema.push(tableInfo); schemaCallback(schema); }; // This function actually make the foursquare API call and // parses the results and passes them back to Tableau myConnector.getData = function(table, doneCallback) { var dataToReturn = []; var hasMoreData = false; var accessToken = tableau.password; var connectionUri = getVenueLikesURI(accessToken); var xhr = $.ajax({ url: connectionUri, dataType: 'json', success: function (data) { if (data.response) { var venues = data.response.venues.items; var ii; for (ii = 0; ii < venues.length; ++ii) { var venue = {'Name': venues[ii].name, 'Latitude': venues[ii].location.lat, 'Longitude': venues[ii].location.lng, 'Address' : venues[ii].location.address}; dataToReturn.push(venue); } table.appendRows(dataToReturn); doneCallback(); } else { tableau.abortWithError("No results found"); } }, error: function (xhr, ajaxOptions, thrownError) { // WDC should do more granular error checking here // or on the server side. This is just a sample of new API. tableau.abortForAuth("Invalid Access Token"); } }); }; // Register the tableau connector, call this last tableau.registerConnector(myConnector); })(); // end of anonymous function ``` ## Config.js Configuration file for Node.js Express web server. ``` // The necessary configuration for your server // Contains credentials for your Foursquare application // And the new redirect path for the OAuth flow module.exports = { 'HOSTPATH': 'http://localhost', 'PORT': 3333, 'CLIENT_ID': 'YOUR_CLIENT_ID', 'CLIENT_SECRET': 'YOUR_CLIENT_SECRET', 'REDIRECT_PATH': '/redirect' }; ``` ## app.js Express web server, using Node.js. ``` // -------------------------------------------------- // // Module Dependencies // -------------------------------------------------- // var express = require('express'); var cookieParser = require('cookie-parser'); var querystring = require('querystring'); var http = require('http'); var request = require('request'); var path = require('path'); var config = require('./config.js'); // Get our config info (app id and app secret) var sys = require('util'); var app = express(); // -------------------------------------------------- // // Express set-up and middleware // -------------------------------------------------- // app.set('port', (process.env.PORT || config.PORT)); app.use(cookieParser()); // cookieParser middleware to work with cookies app.use(express.static(__dirname + '/public')); // -------------------------------------------------- // // Variables // -------------------------------------------------- // var clientID = process.env.FOURSQUARE_CLIENT_ID || config.CLIENT_ID; var clientSecret = process.env.FOURSQUARE_CLIENT_SECRET || config.CLIENT_SECRET; console.log(clientID); console.log(clientSecret); var redirectURI = config.HOSTPATH + ":" + config.PORT + config.REDIRECT_PATH // -------------------------------------------------- // // Routes // -------------------------------------------------- // app.get('/', function(req, res) { console.log("got here"); res.redirect('/index.html'); }); // This route is hit once Foursquare redirects to our // server after performing authentication app.get('/redirect', function(req, res) { // get our authorization code authCode = req.query.code; console.log("Auth Code is: " + authCode); // Set up a request for an long-lived Access Token now that we have a code var requestObject = { 'client_id': clientID, 'redirect_uri': redirectURI, 'client_secret': clientSecret, 'code': authCode, 'grant_type': 'authorization_code' }; var token_request_header = { 'Content-Type': 'application/x-www-form-urlencoded' }; // Build the post request for the OAuth endpoint var options = { method: 'POST', url: 'https://foursquare.com/oauth2/access_token', form: requestObject, headers: token_request_header }; // Make the request request(options, function (error, response, body) { if (!error) { // We should receive { access_token: ACCESS_TOKEN } // if everything went smoothly, so parse the token from the response body = JSON.parse(body); var accessToken = body.access_token; console.log('accessToken: ' + accessToken); // Set the token in cookies so the client can access it res.cookie('accessToken', accessToken, { }); // Head back to the WDC page res.redirect('/index.html'); } else { console.log(error); } }); }); // -------------------------------------------------- // // Create and start our server // -------------------------------------------------- // http.createServer(app).listen(app.get('port'), function(){ console.log('Express server listening on port ' + app.get('port')); }); ``` [(Back to top)](#top) **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # WDC Versions Every web data connector must include a reference to the Tableau WDC library. You can get the latest version of the WDC here: ``` https://connectors.tableau.com/libs/tableauwdc-2.4.latest.js ``` There is also a minified version available: ``` https://connectors.tableau.com/libs/tableauwdc-2.4.latest.min.js ``` The above URLs are the recommended ways of linking to the Tableau WDC and guarantee that you receive patch versions for the current minor version as we release them. If you prefer to opt out of receiving automatic patch versions, you can link directly to a specific patch version, for example: ``` https://connectors.tableau.com/libs/tableauwdc-2.1.1.js https://connectors.tableau.com/libs/tableauwdc-2.1.1.min.js ``` ## Compatibility with versions of Tableau The following table displays which versions of the WDC are compatible with Tableau Desktop: | WDC version | Tableau version | | --- | --- | | `tableauwdc-2.4.0` | 2021.1.2 or later | | `tableauwdc-2.3.0` | 10.4 or later | | `tableauwdc-2.2.0` | 10.2 or later | | `tableauwdc-2.1.0` | 10.1 or later | | `tableauwdc-2.0.2` | 10.0 and later | | `tableauwdc-2.0.0` | 10.0 through 2019.2 | | `tableauwdc-1.1.1` | 9.3 through 2019.2 9.2.4 through 2019.2 9.1.6 through 2019.2 | | `tableauwdc-1.1.0` | 9.2.0 through 9.2.3 9.1.0 through 9.1.5 | In Tableau Desktop, if you try to open a connector that uses an incompatible version of the WDC, you might see an error like the following: ``` The version of Tableau that you are using cannot use the web data connector that you are trying to access. The connector requires at least version 'x.x' of the web data connector API. ``` **Note:** This site is for version 2 of the WDC, and is only be compatible with Tableau 10.0 and later. Version 1 of the WDC is no longer supported. If you are a developer, see [Upgrading from WDC Version 1.x](/v0.0/api/webdataconnector/en-us\docs\wdc_upgrade) for information about migrating your WDC to version 2. **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Web Data Connector Overview Tableau’s Web Data Connector (WDC) lets you connect to data that is accessible over HTTP. A WDC is an HTML file that includes JavaScript code. **Note:** Unlike previous versions, Web Data Connector 3.0 doesn't require that your HTML file is on a web server. ## Components of Web Data Connector 3.0 WDC 3.0 has the following components. ### Extensible Protocol Server The Extensible Protocol Server (EPS) is the server that runs your web data connector. An EPS-based connector is a web application that doesn’t require a web server. ### TACO Toolkit The TACO Toolkit is the command-line interfact that you use to create, build, and package your web data connector. Use the TACO Toolkit to generate template files for a variety of connector types and then edit the files for your specific connector. For more information about creating connectors, see [Build a sample web data connector](https://help.tableau.com/v0.0/api/webdataconnector/en-us/index.html). **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # Web Data Connector SDK License Agreement 🕐 _13 min read_ This Web Data Connector SDK License Agreement (“Agreement”) governs the download, access to and use of the SDK (as defined below). This Agreement is entered between the individual or entity that has downloaded or otherwise accessed the SDK (“you”) and © 2024 Salesforce, Inc. or the applicable Tableau affiliate (“Tableau”). BY DOWNLOADING, INSTALLING OR ACCESSING THE SDK, YOU ARE ACCEPTING ALL OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. YOU AGREE THAT THIS AGREEMENT IS ENFORCEABLE LIKE ANY WRITTEN AGREEMENT SIGNED BY YOU AND LEGALLY BINDING BETWEEN YOU AND TABLEAU. IF YOU DO NOT AGREE TO ALL OF THESE TERMS AND CONDITIONS, DO NOT DOWNLOAD, INSTALL OR ACCESS THE SDK. IF YOU WISH TO USE THE SDK AS AN EMPLOYEE, CONTRACTOR, OR AGENT OF A CORPORATION, PARTNERSHIP OR OTHER ENTITY, THEN YOU MUST BE AUTHORIZED TO SIGN FOR AND BIND THE ENTITY IN ORDER TO ACCEPT THE TERMS OF THIS AGREEMENT AND YOU REPRESENT AND WARRANT THAT YOU HAVE THE RIGHT AND AUTHORITY TO DO SO. 1. Definitions “Connector” means the .taco file and/or related components created by you using the SDK and Tableau application programmatic interfaces (APIs) that enables programmatic interaction between Tableau products and external web databases or applications. “Documentation” means any supporting technical documentation and other materials and information Tableau makes available to you in connection with the SDK. “Product” means any product or service that interoperates with a Connector, and provides functionality to or for Tableau products or services. “SDK” means the web data connector software development kit made available by Tableau to you. “SDK” includes any included content, data, Documentation, files, materials, software, computer code, supplements or updates unless they are provided with separate terms. “Tableau Exchange” means the online “exchange” operated by Tableau currently located at https://exchange.tableau.com/ that offers access to certain solutions that connect to or interoperate with Tableau products and services. 2. License 2.1. License Grant. Subject to all of the terms and conditions of this Agreement, Tableau grants you a limited, worldwide, non-transferable, non-sublicensable, non-exclusive, royalty-free, fully paid-up license to access, download, copy and use the SDK for purposes of developing, testing and maintaining a Connector.. You are expressly prohibited from using the SDK and any Connector in any manner not specified in this Section 2 or the applicable Documentation. 2.2. License Restrictions. You will not (and will not allow any third party to): (a) decompile, disassemble or otherwise reverse engineer the SDK (or any portion of the SDK), or attempt to reconstruct or discover any source code, underlying ideas, algorithms, file formats or programming interfaces of the SDK; (b) distribute, sell, sublicense, rent, lease or use the SDK (or any portion of the SDK) for time sharing, hosting, service provider or any other purposes, or use it on any systems not owned or properly licensed by you; (c) remove any SDK identification, proprietary notice, copyright, trademark, service mark or other notices contained in the SDK; (d) modify any part of the SDK, create a derivative work of any part of the SDK or incorporate the SDK into or with other software, except with respect to any sample code provided in the SDK or to the extent the SDK is incorporated with properly licensed Tableau software or as otherwise expressly authorized in writing by Tableau; (e) publicly disseminate performance information or analysis (including, without limitation, benchmarks) from any source relating to the SDK; or (f) use the SDK or your Connector in violation of any law or of any agreement or privacy policy you have with respect to any third party. 2.3. Ownership: Except for the limited license rights expressly provided in this Section 2, Tableau and its licensors retain all rights, title, and interest, including all intellectual property rights, in and to the SDK and all modifications thereto and derivative works based thereon. All rights not granted by Tableau are reserved. Subject to Tableau’s rights in the SDK, you retain all your rights, title and interest, including all your intellectual property rights, in and to any Connectors that you create. 2.4. Third Party Code. The SDK may contain or be provided with components subject to the terms and conditions of “open source” software licenses (“Open Source Software”). Open Source Software may be identified in the Documentation or separate list that may be made available upon your request. To the extent required by the license that accompanies the Open Source Software, the terms of such license will apply in lieu of the terms of this Agreement only with respect to such Open Source Software, including any provisions governing access to source code, modification or reverse engineering. 2.5. Feedback. If you make available to Tableau any comments, improvements, ideas, suggestions or other feedback to Tableau regarding the SDK (collectively, “Feedback”), Tableau may use, disclose, distribute, reproduce and otherwise exploit such Feedback in any manner without charge or obligation on account of intellectual property rights or otherwise. 2.6. Privacy Policy. You acknowledge that the Tableau Privacy Policy applies if you provide any personal information in connection with this Agreement. 3. Term 3.1. Term and Termination. This Agreement will remain in effect until terminated as set forth in this Section. Tableau may terminate the Agreement at any time, for any reason, upon written notice to you. You may terminate this Agreement at any time upon written notice to Tableau. Upon termination of this Agreement, your license to use the SDK will be terminated, and you will cease any use of the SDK and delete or destroy all copies of the SDK in your possession. If the Agreement is terminated due to your violation of Section 2.1 or 2.2, you will cease distribution of your Connectors and cooperate with Tableau to communicate termination with end users. 3.2. Survival. Sections 2.2 (License Restrictions), 2.3 (Ownership), 2.4 (Third Party Code), 2.5 (Feedback), 3.2 (Survival), 4 (Disclaimer of Warranties), 5 (Support and Maintenance), 6 (Limitation of Liability), 7 (Indemnification), 8 (Confidential Information), 9 (Export Compliance) and 10 (General) survive any termination of this Agreement. 4. Disclaimer of Warranties. THE SDK IS PROVIDED “AS IS.” TABLEAU DOES NOT MAKE ANY REPRESENTATIONS, WARRANTIES, CONDITIONS OR UNDERTAKINGS, EXPRESS OR IMPLIED, STATUTORY OR OTHERWISE, INCLUDING BUT NOT LIMITED TO WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT WITH REGARD TO THE SDK, IN WHOLE OR IN PART, OR ITS HOSTING, AVAILABILITY OR OTHERWISE. YOU MAY HAVE OTHER STATUTORY RIGHTS. HOWEVER, TO THE FULL EXTENT PERMITTED BY LAW, THE DURATION OF STATUTORILY REQUIRED WARRANTIES, IF ANY, WILL BE LIMITED TO THIRTY (30) DAYS FROM THE DATE YOU FIRST DOWNLOAD OR ACCESS THE SDK, WHICHEVER IS EARLIER. 5. Support and Maintenance. Tableau may, in its sole discretion, make available support, updates and maintenance for the SDK, but Tableau will be under no obligation to do so. You, and not Tableau, are solely responsible for providing support, maintenance and updates for your Connectors and Products. 6. Limitation of Liability. TABLEAU WILL NOT BE LIABLE FOR ANY LOSS OF USE, LOST DATA, FAILURE OF SECURITY MECHANISMS, INTERRUPTION OF BUSINESS, UNAVAILABILITY OR ANY INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND (INCLUDING LOST PROFITS OR COSTS OF COVER), REGARDLESS OF THE FORM OF ACTION, WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE), STRICT LIABILITY OR OTHERWISE, EVEN IF TABLEAU OR ANY OF ITS AFFILIATES WAS INFORMED OF THE POSSIBILITY OF SUCH DAMAGES IN ADVANCE. TABLEAU’S ENTIRE LIABILITY UNDER THIS AGREEMENT WILL NOT EXCEED USD $100.00 FOR THE AVOIDANCE OF DOUBT, TABLEAU DOES NOT OWE YOU ANY OBLIGATION OR LIABILITY OF ANY KIND WITH RESPECT TO THE SDK, OR YOUR CONNECTOR OR PRODUCT, OR THE HOSTING, AVAILABILITY, PERFORMANCE OR SUPPORT OF THE FOREGOING. THE PARTIES AGREE THAT THE LIMITATIONS SPECIFIED IN THIS SECTION WILL SURVIVE AND APPLY EVEN IF ANY LIMITED REMEDY SPECIFIED IN THIS AGREEMENT IS FOUND TO HAVE FAILED OF ITS ESSENTIAL PURPOSE. 7. Indemnification. You will indemnify and hold harmless Tableau and its officers, directors, employees and agents from and against all claims, lawsuits, damages, losses and expenses (including reasonable attorneys’ fees) (“Claims”) arising from or relating to: (a) any actual or alleged infringement, violation or misappropriation of any third party intellectual property right or other harm to third parties by a Connector, Product or any content, data, materials, products or services offered through any of the foregoing; (b) any unauthorized representation or warranty made by you to a third party related to Tableau or any of its affiliates, including the SDK or any Tableau products or services; or (c) your breach of this Agreement. Your obligations in this Section 7 are subject to receiving: (i) prompt notice of any Claim (but in any event notice in sufficient time for you to respond without prejudice); (ii) the exclusive right to control and direct the investigation, defense, or settlement of such Claim; and (iii) all reasonable necessary cooperation of Tableau. Tableau may participate in the defense of any Claim by counsel of its own choosing, at its cost and expense. You will not, and do not have authority to, settle any Claim without Tableau’s prior written consent if the settlement requires Tableau to take any action, refrain from taking any action, or admit any liability. 8. Confidential Information. All nonpublic software, code, inventions, know-how, business, technical and financial information, and other confidential and proprietary information you obtain from Tableau or any of its affiliates constitute the confidential property of Tableau (“Confidential Information”). You will hold in confidence and not use or disclose any Confidential Information. Notwithstanding the foregoing, your nondisclosure obligation shall not apply to information that you can document: (a) was rightfully in your possession or known to you prior to receipt of the Confidential Information; (b) is or has become public knowledge through no fault of your own; (c) is rightfully obtained by you from a third party without breach of any confidentiality obligation; (d) is independently developed by your employees who had no access to such information; or (e) is required to be disclosed pursuant to a regulation, law or court order (but only to the minimum extent required to comply with such regulation or order and with advance notice to Tableau). You acknowledge that disclosure of Confidential Information would cause substantial harm to Tableau that could not be remedied by the payment of damages alone and therefore, upon any such disclosure by you, Tableau will be entitled to appropriate equitable relief in addition to whatever other remedies it might have at law. 9. Export Compliance. You are responsible for complying with U.S. export controls and economic sanctions, including the Export Administration Regulations (EAR) and the regulations administered by the Treasury Department’s Office of Foreign Assets Control (OFAC), any applicable import laws, regulations and requirements of the country of importation, and all other applicable trade laws, regulations and requirements which may apply to downloads of software or disclosure of technology subject to U.S. jurisdiction (collectively, “Trade Laws”), and for any violation of applicable Trade Laws. You agree that: (a) you will not allow any third party to export, re-export, or transfer any part of the SDK, or any of your Connectors or Products in violation of applicable Trade Laws; and (b) you have in effect policies and procedures reasonably designed to ensure compliance with applicable Trade Laws, including determining the export classifications and licensing requirements applicable to any Connectors and Products. You represent, warrant and covenant that you are not, and that your subsidiaries and their respective directors, officers, or employees are not: (i) identified on any U.S. government list of prohibited or restricted end user, including the OFAC list of Specially Designated Nationals and the EAR Entity List, Denied Parties List or Unverified List; (ii) located in, organized under the laws of, or a resident of, any jurisdiction subject to comprehensive U.S. sanctions; or (iii) owned or controlled by any of the parties covered by (i) and (ii). 10. General 10.1. Assignment. This Agreement will bind and inure to the benefit of each party’s permitted successors and assigns. Tableau may assign this Agreement to any affiliate or in connection with a merger, reorganization, acquisition or other transfer of all or substantially all of Tableau’s assets or voting securities. You may not assign or transfer this Agreement, in whole or in part, without Tableau’s written consent. Any attempt to transfer or assign this Agreement without such written consent will be null and void. 10.2. Severability. If any provision of this Agreement shall be adjudged by any court of competent jurisdiction to be unenforceable or invalid, that provision shall be limited to the minimum extent necessary so that this Agreement shall otherwise remain in effect. 10.3. Governing Law. This Agreement will be governed by and construed in accordance with the laws of the State of Washington and the United States without regard to conflicts of laws provisions. The jurisdiction and venue for actions related to the subject matter hereof will be the state and federal courts located in Seattle, Washington, and both parties hereby submit to the personal jurisdiction of such courts. 10.4. Notices and Reports. Any notice or report hereunder will be in writing. If to Tableau, such notice or report will be sent to Tableau at 1621 N. 34th St., Seattle, WA 98103 to the attention of “Legal Department”. If to Tableau by email, such notice or report will be sent to legal@tableau.com. If to you, such notice or report will be sent to the physical address (or, if by email, the email address) you provided upon placing your order. Notices and reports will be deemed given: (a) upon receipt if by personal delivery; (b) upon receipt if sent by certified or registered mail (return receipt requested); or (c) one day after it is sent if by next day delivery by a major commercial delivery service. Any notices and reports sent by email will be effective upon receipt of the same. 10.5. Government End-Users. The SDK is commercial computer software. If the user or licensee of the SDK is an agency, department, or other entity of the United States Government, the use, duplication, reproduction, release, modification, disclosure, or transfer of the SDK, or any related Documentation of any kind, including technical data and manuals, is restricted by a license agreement or by the terms of this Agreement in accordance with Federal Acquisition Regulation 12.212 for civilian purposes and Defense Federal Acquisition Regulation Supplement 227.7202 for military purposes. The SDK was developed fully at private expense. All other use is prohibited. 10.6. Modifications. Tableau may modify this Agreement from time to time by giving notice to you in accordance with Section 10.4. The modified Agreement will become effective on the date set forth in the notice, and all other changes will become effective upon posting of the change. If you access or use the SDK after the effective date, that use will constitute your acceptance of any revised terms and conditions. 10.7. Amendments; Waivers. Except as otherwise provided in this Agreement, no supplement, modification, or amendment of this Agreement will be binding, unless executed in writing by a duly authorized representative of each party to this Agreement. No waiver will be implied from conduct or failure to enforce or exercise rights under this Agreement, nor will any waiver be effective unless in a writing signed by a duly authorized representative on behalf of the party claimed to have waived. 10.8. Entire Agreement. This Agreement is the complete and exclusive statement of the mutual understanding of the parties and supersedes and cancels all previous written and oral agreements and communications between you and Tableau relating to the SDK. **Deprecated** - This repository will be removed with the Tableau 26.3 release. The Web Data Connector 3.0 framework is deprecated and will not receive further updates. Migrate to the [REST API Connector on Tableau Exchange](https://exchange.tableau.com/products/1111)—built by Tableau, supports JSON and CSV over HTTP GET, Basic/Bearer/OAuth authentication, and runs on Tableau 2023.3 and later. Note: this connector is extract-only and requires a JDBC driver installation. # What's New 🕐 _3 min read_ # Tableau TACO Toolkit 2.0 _October 2023_ This release contains updated [connector boilerplates](/v0.0/api/webdataconnector/en-us/docs/wdc_samples.html). This release also includes an update to the TACO Toolkit [Web Data Connector SDK](/v0.0/api/webdataconnector/en-us/reference/index.html) modules and documentation. # Tableau TACO Toolkit 1.3 _November 2022_ The Web Data Connector version 3.0 is a complete rewrite of the web data connector model used in previous versions. Web Data Connector 3.0 offers you extended flexibility and a streamlined toolset to create connectors for web-based data that isn’t easily retrieved using conventional ODBC or JDBC drivers. With the Web Data Connector 3.0 SDK, you can build connectors to virtually any web data source faster and more easily than ever before. The Web Data Connector 3.0 framework revamps the web data connector developer experience by eliminating the hosting overhead of the earlier versions. This gives integrated authentication capabilities and modernizes the SDK tools, libraries, and API. These changes reduce the complexity for building a new web data connector. Also, with the new framework, web data connectors appear as named connections in Tableau and can be distributed through Tableau Exchange. This makes the connectors more discoverable and usable across the Tableau platform. ## TACO Toolkit We created the TACO Toolkit to help you develop your connectors. The TACO Toolkit is an [npm](https://www.npmjs.com/) package. The toolkit contains a CLI, a software development kit (SDK), and the Extensible Protocol Server (EPS). - The TACO CLI provides a global way to create and build a TACO project that contains your connector source code. The CLI can also pack a built TACO project into a Tableau TACO connector (the `.taco` file). - The TACO SDK provides application programming interfaces (APIs) to help you develop your TACO projects (the source code). The SDK also provides some npm scripts, which allow you to build and test your projects with the standard npm commands. - The EPS is started by the TACO CLI or the npm scripts to load and test your connector source code.connector. ## Major features of connectors created with the TACO Toolkit - **Easier to find available connectors**: Connectors are easier to find because they can be listed directly in the Tableau Exchange. - **Listed within products**: Connectors you add appear as named connectors directly in Tableau Desktop, Tableau Prep Builder, and Tableau Server web authoring. - **Work across all products**: Connectors work across all Tableau products including Tableau Desktop, Tableau Server, Tableau Prep, Tableau Catalog, and Tableau Cloud. Only Tableau managed connectors can be deployed to Tableau Cloud. - **Simpler development experience**: We have made the development experience simpler and faster by doing the following. - Added direct support for modern authentication flows including OAuth 2.0 & OpenID. Because our SDK for WDC, ODBC, and JDBC are shared, we’re also sharing authentication support. - The [SDK](https://help.tableau.com/v0.0/api/webdataconnector/en-us/reference/index.html) now bundles everything a developer needs to get started including a more robust simulator and test framework - The time required for you to create a connector is many times faster. You can theoretically be up and running with a boilerplate connector in under a minute compared to 20-30 minutes to have a basic connector running in the current WDC 2.x framework - No hosting required: You don’t need a web server to host the WDC connector or OAuth proxy, saving you management time and the cost of hosting.