Is SeekIt — Get 1TB Free Storage safe?
SeekIt sends search queries and browser context telemetry to analytics.seekit.com when users use search.seekit.com.
When a tab navigates to a SeekIt search results page with a query, the service worker records the query, previous or referring URL details, tab and window context, counters, engagement metrics, install metadata, and remote-config labels. It POSTs those fields to analytics.seekit.com/track, and also records a daily active user event on the first search of the day.
Who publishes itPower Search in Chrome - no other listings under this identity, 1 shared hostname
Power Search in Chrome - no other listings under this identity, 1 shared hostname
What this publisher told the store about itself, and the other listings that told it the same thing.
Shared hosts - 1 hostname
Hostnames hardcoded in this extension that few other listings call. That can mean one operator behind both, and it can equally mean a small shared vendor, so it is context rather than a conclusion. Hosts that many listings call are left out: they are services, not connections.
AI-generated. Findings may contain errors. Those marked Verified have been manually reviewed.
Publishers can request a review.
Findings
SeekIt Sends Your Search Queries and Tab Context to analytics.seekit.com
When you search on SeekIt, via the omnibox or search.seekit.com results, its service worker POSTs the search to analytics.seekit.com/track: term, install ID, referring domain, tab/window counts, active-tab status, and search streak.
- Severity
- Medium unwanted
- Type
- Unexpected
- CWE
- CWE-359
- Source
- Dynamic sandbox
You search using SeekIt, either from the omnibox or by opening a search.seekit.com results page with a query.
The background service worker separately reports your search term and details about your open tabs to SeekIt's analytics server.
This telemetry request is distinct from the request that returns your search results, and it fires on every search.
- Your search querybest noise cancelling headphones under 200
The exact text you searched for is sent to the analytics endpoint, separate from the request that returns your results.
- Persistent install identifierref_rzyssacVIYqisQFg25MCMeFE0UI0oXVJ
A random ID assigned to your install and reused on every analytics event, letting SeekIt link all of your searches together over time.
- Where you came fromwelcome.seekit.com
The domain of the page you were on immediately before the search, sent as referring_domain and inside source_hints.
- Open tabs and windowstab_count: 3, is_active_tab: false, has_multiple_windows: false
How many tabs you have open, whether the search tab is active, and whether you have more than one window open.
- Search history counterstotal_searches_all_time: 1, search_streak_days: 1
A running total of every search you've made since installing SeekIt and your consecutive-day search streak.
- Engagement scoreengagement_score: 4
A computed score summarizing how actively you use the extension, built from your search count, streak, and session activity.
200 OK
- Content-Type
- application/json
{ "event": "search_performed", "distinct_id": "ref_rzyssacVIYqisQFg25MCMeFE0UI0oXVJ", "properties": { "query": "best noise cancelling headphones under 200", "source": "omni", "source_hints": { "subid": "chrome-extension", "referrer": "https://welcome.seekit.com/chrome", "url_source": "omni" }, "tab_count": 3, "is_active_tab": false, "referring_domain": "welcome.seekit.com", "has_multiple_windows": false, "session_searches": 1, "session_duration_seconds": 21, "search_streak_days": 1, "total_searches_all_time": 1, "engagement_score": 4, "extension_version": "3.5.4" }}The listener that reads your query, and the pipeline that reports it.
Search-navigation listener (annotated)
service_worker.js// Fires on every tab navigation. Only acts when the new URL is a// search.seekit.com results page carrying a "q" query parameter.chrome.tabs.onUpdated.addListener(async (tabId, changeInfo, tab) => { if (changeInfo.url) { const previousUrl = tabPreviousUrls.get(tabId) || ''; const suppressedUrl = tabRewriteSuppress.get(tabId); if (suppressedUrl === changeInfo.url) { tabRewriteSuppress.delete(tabId); } else if (tabRewriteSuppress.has(tabId)) { tabRewriteSuppress.delete(tabId); tabPreviousUrls.set(tabId, changeInfo.url); return; } try { const url = new URL(changeInfo.url); // Match a SeekIt search-results URL and read the query text. if (url.hostname === 'search.seekit.com' && (url.pathname === '/' || url.pathname === '/search' || url.pathname === '/serp')) { const query = url.searchParams.get('q'); if (query) { const subid = url.searchParams.get('subid'); const isOmniboxSearch = (subid === 'chrome-extension') || (!previousUrl || previousUrl === '' || previousUrl === 'about:blank'); // Classify where the search came from (omnibox shortcut vs. // clicking a result on the search page itself). let source = 'unknown'; if (subid === 'chrome-extension') { source = ANALYTICS_SOURCE.OMNI; } else if (previousUrl && (previousUrl.includes('s1search.co') || previousUrl.includes('search.seekit.com'))) { const urlParams = new URLSearchParams(url.search); const hasOtherSubid = urlParams.has('subid') && urlParams.get('subid') !== 'chrome-extension'; if (hasOtherSubid) { source = ANALYTICS_SOURCE.SERP; } else if (!urlParams.has('subid')) { source = ANALYTICS_SOURCE.SERP; } else { source = ANALYTICS_SOURCE.SERP; } } else if (!previousUrl || previousUrl === '' || previousUrl === 'about:blank') { source = ANALYTICS_SOURCE.OMNI; } else if (previousUrl && !previousUrl.includes('google.com') && !previousUrl.includes('bing.com')) { source = ANALYTICS_SOURCE.OMNI; } else { source = ANALYTICS_SOURCE.OMNI; } if (source === ANALYTICS_SOURCE.OMNI && url.hostname === 'search.seekit.com') { const currentUrl = new URL(changeInfo.url); const existingRef = currentUrl.searchParams.get('ref'); const alias = await getOrCreateAlias(existingRef); chrome.tabs.sendMessage(tabId, { type: 'update_url_params', ref: alias, source: ANALYTICS_SOURCE.OMNI, currentUrl: changeInfo.url }).catch(() => { }); } // Read tab_count / is_active_tab / referring_domain / // has_multiple_windows before the analytics call. const contextualMeta = await getContextualSearchMetadata(tabId, previousUrl); if (typeof SeekItAnalytics !== 'undefined' && SeekItAnalytics.trackSearch) { // Primary path: reports the query + browser context to // analytics.seekit.com/track via SeekItAnalytics.trackSearch. SeekItAnalytics.trackSearch(query, source, { source_hints: { subid: subid || 'none', referrer: previousUrl || 'none', url_source: source }, ...contextualMeta }); // Track daily_active_user on first search of the day (search-based, not install-based) SeekItAnalytics.trackDailyActiveOnSearch(); } else { // Fallback path: same event, sent with a direct fetch() if the // SeekItAnalytics module hasn't loaded yet. await fallbackTrackSearch(query, source, { source_hints: { subid: subid || 'none', referrer: previousUrl || 'none', url_source: source }, ...contextualMeta }); await fallbackTrackDailyActive(); } } } // Separately: flag when the user leaves SeekIt for a competing // search engine right after a SeekIt search. if (previousUrl && previousUrl.includes('search.seekit.com')) { const competitorDomains = ['google.com', 'bing.com', 'duckduckgo.com', 'yahoo.com']; for (const competitor of competitorDomains) { if (changeInfo.url.includes(competitor)) { if (typeof SeekItAnalytics !== 'undefined' && SeekItAnalytics.trackCompetitorPivot) { SeekItAnalytics.trackCompetitorPivot(competitor); } break; } } } } catch (error) { } tabPreviousUrls.set(tabId, changeInfo.url); }});Event enrichment and POST (annotated)
js/seekit-analytics-simple.js // Builds the event envelope (distinct_id, timestamp, session_id) and // POSTs it to analytics.seekit.com/track. Falls back to a local // offline queue if the request fails. async sendEvent(eventName, properties = {}) { if (!this.initialized) { await this.initialize(); } const eventData = { event: eventName, distinct_id: this.userId, // persistent per-install alias properties: { ...properties, extension_version: chrome.runtime.getManifest().version, timestamp: new Date().toISOString(), session_id: this.sessionId } }; try { const response = await fetch(this.ANALYTICS_ENDPOINT, { // https://analytics.seekit.com/track method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(eventData) }); if (!response.ok) { await this.queueOfflineEvent(eventData); return false; } return true; } catch (error) { await this.queueOfflineEvent(eventData); return false; } }, // Attaches session/search-history telemetry, an engagement score, // remote-config labels, and install/device metadata before calling // sendEvent(). This is what turns a bare "search_performed" event // into one carrying tab context and usage history. async sendEventWithEnrichment(eventName, properties = {}) { const [sessionTelemetry, configParams, installMetadata] = await Promise.all([ this.getSessionTelemetry(), // session_searches, search_streak_days, total_searches_all_time, ... this.getRemoteConfigParams(), // experiment_bucket, ab_variant, feature_flags this.getInstallMetadata() // install_hour/day/weekend, screen_resolution, language, timezone ]); const engagementData = this.calculateEngagementScore(sessionTelemetry); const enrichedProperties = { ...properties, ...sessionTelemetry, ...engagementData, ...configParams, install_hour: installMetadata.install_hour, install_day_of_week: installMetadata.install_day_of_week, install_is_weekend: installMetadata.install_is_weekend, install_time_bucket: installMetadata.install_time_bucket, screen_resolution: installMetadata.screen_resolution, user_language: installMetadata.language, user_timezone: installMetadata.timezone }; return this.sendEvent(eventName, enrichedProperties); }, // Called on every matched search-results navigation. Updates the // local search-streak/total counters, then sends "search_performed" // with the query text through the enrichment pipeline above. async trackSearch(query, source = 'omnibox', additionalProps = {}) { this.searchesThisSession += 1; this.lastSearchTime = Date.now(); const stored = await chrome.storage.local.get([ 'total_searches_all_time', 'last_search_date', 'search_streak_days' ]); const today = new Date().toDateString(); const yesterday = new Date(Date.now() - 86400000).toDateString(); let newStreak = stored.search_streak_days || 0; if (stored.last_search_date === yesterday) { newStreak += 1; } else if (stored.last_search_date !== today) { newStreak = 1; } const newTotal = (stored.total_searches_all_time || 0) + 1; await chrome.storage.local.set({ total_searches_all_time: newTotal, last_search_date: today, search_streak_days: newStreak }); await this.sendEventWithEnrichment('search_performed', { query: query, // your exact search text source: source, search_number_this_session: this.searchesThisSession, ...additionalProps // source_hints + tab_count/is_active_tab/etc. }); },- analytics.seekit.com
Receives the search_performed and daily_active_user events: your persistent install ID, search query, and browser-context fields. First-party, SeekIt's own domain.
What it can do
Permissions this extension asks for, as declared in version 3.5.4. Asking for a permission is not a finding on its own - it is what the extension can do if it chooses to.
Read and change your data on searchinchrome.com
*://*.searchinchrome.com/*
Read and change your data on seekit.com
*://*.seekit.com/*
Schedule its own background tasks
alarms
Add items to the right-click menu
contextMenus
See the address and title of every tab you have open
tabs
Store data in your browser
storage
Run searches with your default search engine
search
Where it sends data
Destinations our analysis observed SeekIt — Get 1TB Free Storage contacting. Sending data somewhere is not a finding on its own - an extension that syncs your settings has to talk to its own server - but it is where your data can go, and who else it goes to.
- analytics.seekit.com
SeekIt — Get 1TB Free Storage sends data to analytics.seekit.com. No other extension we have analysed sends data here.