-
Notifications
You must be signed in to change notification settings - Fork 30
example(refiner): added new connector for refiner connector #437
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
fivetran-sushmitha
wants to merge
21
commits into
main
Choose a base branch
from
refiner
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
b3be037
example(refiner): added new connector for refiner connector
fivetran-sushmitha 4470051
Merge branch 'main' of https://github.com/fivetran/fivetran_connector…
fivetran-sushmitha 6f66966
Address review comments
fivetran-sushmitha b0693d7
Update connectors/refiner/README.md
fivetran-sushmitha 96d3658
Update connectors/refiner/README.md
fivetran-sushmitha 1404d1d
Update connectors/refiner/connector.py
fivetran-sushmitha 5603455
Update connectors/refiner/connector.py
fivetran-sushmitha 302cbad
Update connectors/refiner/connector.py
fivetran-sushmitha 1227017
address comments
fivetran-sushmitha 745b7c1
address comments
fivetran-sushmitha d904b9e
Address review comments
fivetran-sushmitha a9ae0c2
Update connectors/refiner/README.md
fivetran-sushmitha dc0e300
Update connectors/refiner/README.md
fivetran-sushmitha b738db9
Update connectors/refiner/README.md
fivetran-sushmitha 2cce4ee
Update connectors/refiner/README.md
fivetran-sushmitha d7193bd
Update connectors/refiner/README.md
fivetran-sushmitha 27d6403
Update connectors/refiner/README.md
fivetran-sushmitha cb34563
Update connectors/refiner/README.md
fivetran-sushmitha 6f62a97
Update connectors/refiner/README.md
fivetran-sushmitha c7ed243
Update connectors/refiner/README.md
fivetran-sushmitha 65e50ad
Update connectors/refiner/README.md
fivetran-sushmitha File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,187 @@ | ||
| # Connector SDK Refiner Survey Analytics Connector Example | ||
|
|
||
| ## Connector overview | ||
| This custom Fivetran connector extracts survey response data from the [Refiner](https://refiner.io) REST API and loads it into your destination. The connector fetches NPS surveys, questions, responses, and respondent data keyed by user ID, enabling product teams to analyze survey feedback alongside user behavior data for comprehensive product analytics. | ||
|
|
||
| ## Requirements | ||
| - [Supported Python versions](https://github.com/fivetran/fivetran_connector_sdk/blob/main/README.md#requirements) | ||
| - Operating system: | ||
| - Windows: 10 or later (64-bit only) | ||
| - macOS: 13 (Ventura) or later (Apple Silicon [arm64] or Intel [x86_64]) | ||
| - Linux: Distributions such as Ubuntu 20.04 or later, Debian 10 or later, or Amazon Linux 2 or later (arm64 or x86_64) | ||
|
|
||
| ## Getting started | ||
| Refer to the [Connector SDK Setup Guide](https://fivetran.com/docs/connectors/connector-sdk/setup-guide) to get started. | ||
|
|
||
| ## Features | ||
| - Extracts survey metadata from the `/forms` endpoint with full configuration and question details | ||
| - Extracts survey responses from the `/responses` endpoint with incremental sync support | ||
| - Creates normalized tables for surveys, questions, responses, answers, and respondents | ||
| - Implements incremental syncs based on `updated_at` timestamps with automatic state management | ||
| - Processes all paginated data automatically using cursor-based pagination for large datasets | ||
| - Implements exponential backoff for API reliability (3 retries with progressive delays) | ||
| - Flattens nested JSON structures into table columns automatically | ||
| - Checkpoints progress during pagination to ensure resumability for large datasets | ||
| - Extracts and normalizes nested arrays (questions, answers) into child tables with foreign keys | ||
| - Keys user-level data by user ID for joining with product usage data | ||
|
|
||
| ## Configuration file | ||
| The configuration requires your Refiner API key and optionally a start date for the initial sync. | ||
|
|
||
| ```json | ||
| { | ||
| "api_key": "<YOUR_REFINER_API_KEY>", | ||
| "start_date": "<OPTIONAL_START_DATE_UTC_ISO8601_FORMAT>" | ||
| } | ||
| ``` | ||
|
|
||
| ### Configuration parameters | ||
| - `api_key` (required) - Your Refiner API key for Bearer token authentication. | ||
| - `start_date` (optional) - UTC datetime in ISO 8601 format with 'Z' suffix (e.g., "2025-01-01T00:00:00Z"). If not provided, sync starts from EPOCH time (1970-01-01T00:00:00Z) to capture all historical data. | ||
|
|
||
| Note: Ensure that the `configuration.json` file is not checked into version control to protect sensitive information. | ||
|
|
||
| ## Requirements file | ||
| The `requirements.txt` file specifies additional Python libraries required by the connector. Following Fivetran best practices, this connector does not require additional dependencies beyond the SDK-provided packages. | ||
|
|
||
| Note: The `fivetran_connector_sdk:latest` and `requests:latest` packages are pre-installed in the Fivetran environment. To avoid dependency conflicts, do not declare them in your `requirements.txt`. | ||
fivetran-sahilkhirwal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| ## Authentication | ||
| The connector uses Bearer token authentication via the `Authorization` header. To obtain your API key: | ||
|
|
||
| 1. Log in to your [Refiner](https://refiner.io) account. | ||
| 2. Go to **Settings** > **Integrations** > **API**. | ||
| 3. Copy your API key. | ||
| 4. Add the API key to your `configuration.json` file as shown above. | ||
|
|
||
| The API key is included in every request as `Authorization: Bearer YOUR_API_KEY`. | ||
|
|
||
| ## Pagination | ||
| The connector handles pagination automatically using the Refiner API's cursor-based pagination structure. The API supports the following pagination parameters: | ||
| - `page` - Current page number (starts at 1) - used as fallback | ||
| - `page_length` - Number of items per page (default: 100) | ||
| - `next_page_cursor` - Cursor token for cursor-based pagination | ||
|
|
||
| The connector uses cursor-based pagination for optimal performance with large datasets: | ||
| - Each sync processes all paginated data completely using the `pagination.next_page_cursor` response field. | ||
| - Cursor-based pagination is more efficient than page-based pagination for large datasets and is recommended by the Refiner API documentation. | ||
| - Pagination state is not persisted between sync runs for cleaner state management. | ||
| - Uses the `date_range_start` parameter to filter responses from the API directly for incremental syncs. | ||
|
|
||
| Pagination logic is implemented in: | ||
| - `fetch_surveys()` - Paginate through all surveys | ||
| - `fetch_responses()` - Paginate through responses with date filtering | ||
|
|
||
| ## Data handling | ||
| The connector processes survey and response data with an optimized incremental sync strategy: | ||
fivetran-sushmitha marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| ### Tables and relationships | ||
| - `surveys` - Survey metadata including configuration (parent table) | ||
| - `questions` - Questions extracted from survey config (child of surveys) | ||
| - `responses` - Individual survey responses (linked to surveys and respondents) | ||
| - `answers` - Answer data for each question in a response (child of responses) | ||
| - `respondents` - User/contact information keyed by user ID (parent for responses) | ||
|
|
||
| ### Incremental sync strategy | ||
| - Responses: Incremental sync using `last_response_sync` timestamp from state to fetch only new/updated responses since last successful sync | ||
| - Surveys and Contacts: Full sync on every run (the Refiner API does not support date filtering for these endpoints) | ||
| - Initial response sync uses `start_date` from configuration (if provided) or EPOCH time (1970-01-01T00:00:00Z) as fallback | ||
| - Checkpoint every 1000 records during large response syncs to enable resumability | ||
| - Checkpoint after each page for surveys and contacts to preserve progress | ||
| - Final checkpoint saves the complete state only after successful sync completion | ||
|
|
||
| ### Data transformation | ||
| - JSON flattening: Nested dictionaries converted to underscore-separated columns (e.g., `config.theme.color` becomes `config_theme_color`) | ||
| - Array handling - Arrays converted to JSON strings when stored in parent tables, or normalized to child tables when appropriate | ||
| - Child table extraction - Questions extracted from survey config (`config.form_elements`) and answers extracted from response data are stored in dedicated child tables to preserve relational structure | ||
| - Smart exclusion - Relational data like `form_elements` is excluded from the flattened parent table to avoid duplication, as it's already normalized into the questions table | ||
| - Foreign keys - Child tables maintain relationships via parent primary keys (`survey_uuid`, `response_uuid`) | ||
| - Type safety - Configuration validation ensures required fields exist before processing | ||
|
|
||
| ### Key functions | ||
| - `validate_configuration()`: Validates required API key configuration | ||
| - `make_api_request()` - Centralized API calling with retry logic and error handling | ||
| - `flatten_dict()` - Recursive JSON structure flattening for table columns with smart exclusion of relational data | ||
| - `fetch_surveys()` - Main survey sync with pagination, question extraction, and page-level checkpointing | ||
| - `fetch_questions()` - Extract questions from survey configuration into child table | ||
| - `fetch_contacts()` - Full contact sync with pagination and page-level checkpointing | ||
| - `fetch_responses()` - Incremental response sync with date-based filtering and record-level checkpointing | ||
| - `fetch_answers()` - Extract answers from response data into child table | ||
| - `fetch_respondent()` - Extract or update respondent information | ||
|
|
||
| The connector maintains a clean state with the `last_response_sync` timestamp for incremental response syncing, automatically advancing after each successful sync to ensure reliable incremental syncs without data duplication or gaps. Surveys and contacts are fully synced on each run. | ||
|
|
||
| ## Error handling | ||
| The connector implements comprehensive error handling with multiple layers of protection: | ||
|
|
||
| ### Configuration validation (`validate_configuration()`) | ||
| - Validates the required `api_key` field exists and is not empty | ||
| - Provides clear error messages for configuration issues | ||
|
|
||
| ### API request resilience (`make_api_request()`) | ||
| - Implements retry logic with exponential backoff (3 attempts with progressive delays: 2s, 4s, 8s) | ||
| - Handles HTTP errors (4xx, 5xx), timeouts, and network issues gracefully | ||
| - Fail-fast for permanent errors (401, 403, 404) without retrying | ||
| - Detailed logging for debugging API connectivity problems | ||
|
|
||
| ### Data processing safeguards | ||
| - Graceful handling of missing or malformed API response structures | ||
| - Safe dictionary access patterns with `.get()` and type checks to prevent AttributeError and KeyError exceptions | ||
| - Skips records missing required identifiers (uuid) with warnings | ||
| - Error handling for malformed timestamps with warning logs | ||
| - Proper exception propagation with descriptive RuntimeError messages from API layer | ||
|
|
||
| ### Checkpoint recovery | ||
| - Checkpoints after each page during survey and contact syncs to preserve progress | ||
| - Checkpoints every 1000 records during large response syncs enable recovery from interruptions | ||
| - State tracking allows sync to resume from the last successful checkpoint | ||
| - Final checkpoint saved after complete successful sync | ||
|
|
||
| Unhandled exceptions in the `update()` function will propagate and be logged by the Fivetran platform for troubleshooting. The connector's error handling strategy focuses on resilience at the API request level and safe data processing with proper validation. | ||
fivetran-sahilkhirwal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| ## Tables created | ||
|
|
||
| The connector creates the following tables in your destination: | ||
|
|
||
| | Table name | Primary key | Description | | ||
| |------------|-------------|-------------| | ||
| | `surveys` | `uuid` | Survey metadata and configuration with flattened JSON properties | | ||
| | `questions` | `survey_uuid`, `question_id` | Questions extracted from survey configuration (child table) | | ||
| | `responses` | `uuid` | Individual survey responses with foreign keys to surveys and respondents | | ||
| | `answers` | `response_uuid`, `question_id` | Answer data for each question (child table) | | ||
| | `respondents` | `user_id` | User/contact information for survey respondents | | ||
|
|
||
| ### Schema details | ||
|
|
||
| `surveys` table: | ||
| - Contains flattened survey configuration and metadata | ||
| - Nested config properties are flattened to underscore-separated columns | ||
| - Primary key: `uuid` | ||
|
|
||
| `questions` table: | ||
| - Extracted from survey `config.form_elements` | ||
| - Foreign key: `survey_uuid` (references surveys.uuid) | ||
| - Composite primary key: `survey_uuid`, `question_id` | ||
| - Columns: `question_text`, `question_type`, `required`, `options` (JSON) | ||
|
|
||
| `responses` table: | ||
| - Individual survey submissions | ||
| - Foreign keys: `survey_uuid` (references surveys.uuid), `user_id` (references respondents.user_id) | ||
| - Primary key: `uuid` | ||
| - Key timestamp fields: `completed_at`, `last_shown_at`, `last_data_reception_at`, `created_at`, `updated_at` | ||
| - Score field for NPS/rating responses | ||
|
|
||
| `answers` table: | ||
| - Answer values for each question in a response | ||
| - Foreign key: `response_uuid` (references responses.uuid) | ||
| - Composite primary key: `response_uuid`, `question_id` | ||
| - `answer_value` stored as string or JSON depending on data type | ||
|
|
||
| `respondents` table: | ||
| - User/contact information keyed by user ID for joins with product usage data | ||
| - Primary key: `user_id` | ||
| - Populated from both response data (via `fetch_respondent()`) and dedicated contacts endpoint (via `fetch_contacts()`) | ||
| - Columns: `contact_uuid`, `remote_id`, `email`, `display_name`, `first_seen_at`, `last_seen_at`, `last_form_submission_at`, `last_tracking_event_at`, `attributes` (JSON), `segments` (JSON) | ||
|
|
||
| ## Additional considerations | ||
| The examples provided are intended to help you effectively use Fivetran's Connector SDK. While we've tested the code, Fivetran cannot be held responsible for any unexpected or negative consequences that may arise from using these examples. For inquiries, please reach out to our Support team. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| { | ||
| "api_key": "<YOUR_REFINER_API_KEY>", | ||
| "start_date": "<OPTIONAL_START_DATE_UTC_ISO8601_FORMAT>" | ||
fivetran-sahilkhirwal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.