diff --git a/client/src/app/app-config.service.ts b/client/src/app/app-config.service.ts
index 604ad74d6184fe35542b8220aa14559210f06cce..5c27615b80d28b2ceb482d880379fcbe06f8b4ff 100644
--- a/client/src/app/app-config.service.ts
+++ b/client/src/app/app-config.service.ts
@@ -5,6 +5,7 @@ export class AppConfigService {
     public apiUrl: string;
     public servicesUrl: string;
     public baseHref: string;
+    public sampEnabled: string;
     public authenticationEnabled: boolean;
     public ssoAuthUrl: string;
     public ssoRealm: string;
diff --git a/client/src/app/app-init.ts b/client/src/app/app-init.ts
index af48b11b16bbd43a264d5afd5618b7aa210335e8..630038a94684e61be0ee34a5a36241b631fa6800 100644
--- a/client/src/app/app-init.ts
+++ b/client/src/app/app-init.ts
@@ -8,11 +8,13 @@ import { AppConfigService } from './app-config.service';
 import { initializeKeycloak } from 'src/app/auth/init.keycloak';
 
 import { environment } from 'src/environments/environment';
+import { firstValueFrom } from 'rxjs';
 
 function appInit(http: HttpClient, appConfigService: AppConfigService, keycloak: KeycloakService, store: Store<{ }>) {
     return () => {
-        return http.get(getClientSettingsUrl())
-            .toPromise()
+        const source$ = http.get(getClientSettingsUrl());
+
+        return firstValueFrom(source$)
             .then(data => {
                 Object.assign(appConfigService, data);
                 appConfigService.apiUrl = environment.apiUrl;
diff --git a/client/src/app/app.module.ts b/client/src/app/app.module.ts
index cca4aece56fc59af597c3db12456c7952748f33d..4552174d0de81d1dc4e4107ec5279653161565e8 100644
--- a/client/src/app/app.module.ts
+++ b/client/src/app/app.module.ts
@@ -24,6 +24,7 @@ import { CustomSerializer } from './custom-route-serializer';
 import { CoreModule } from './core/core.module';
 import { AuthModule } from './auth/auth.module';
 import { MetamodelModule } from './metamodel/metamodel.module';
+import { SampModule } from './samp/samp.module';
 import { AppComponent } from './core/containers/app.component';
 import { AppConfigService } from './app-config.service';
 import { appInitializer } from './app-init';
@@ -36,6 +37,7 @@ import { appInitializer } from './app-init';
         CoreModule,
         AuthModule,
         MetamodelModule,
+        SampModule,
         AppRoutingModule,
         StoreModule.forRoot(reducers, {
             metaReducers,
diff --git a/client/src/app/instance/instance.reducer.ts b/client/src/app/instance/instance.reducer.ts
index ed942d2b4006a1d7be4b27325465d2089b8d506e..3be0935a92e04797c5cd669a3721253f0bf81a81 100644
--- a/client/src/app/instance/instance.reducer.ts
+++ b/client/src/app/instance/instance.reducer.ts
@@ -12,7 +12,6 @@ import { combineReducers, createFeatureSelector } from '@ngrx/store';
 import { RouterReducerState } from 'src/app/custom-route-serializer';
 import * as search from './store/reducers/search.reducer';
 import * as searchMultiple from './store/reducers/search-multiple.reducer';
-import * as samp from './store/reducers/samp.reducer';
 import * as coneSearch from './store/reducers/cone-search.reducer';
 import * as detail from './store/reducers/detail.reducer';
 import * as svomJsonKw from './store/reducers/svom-json-kw.reducer';
@@ -26,7 +25,6 @@ import * as downloadFile from './store/reducers/download-file.reducer';
 export interface State {
     search: search.State,
     searchMultiple: searchMultiple.State,
-    samp: samp.State,
     coneSearch: coneSearch.State
     detail: detail.State,
     svomJsonKw: svomJsonKw.State,
@@ -36,7 +34,6 @@ export interface State {
 const reducers = {
     search: search.searchReducer,
     searchMultiple: searchMultiple.searchMultipleReducer,
-    samp: samp.sampReducer,
     coneSearch: coneSearch.coneSearchReducer,
     detail: detail.detailReducer,
     svomJsonKw: svomJsonKw.svomJsonKwReducer,
diff --git a/client/src/app/instance/search/components/result/datatable-actions.component.html b/client/src/app/instance/search/components/result/datatable-actions.component.html
index a9a9a6e3e0832fd10dcd5ca89b56f1ee32797a87..f54031521f73c94cb57c0d2f0f02a0c63a475e85 100644
--- a/client/src/app/instance/search/components/result/datatable-actions.component.html
+++ b/client/src/app/instance/search/components/result/datatable-actions.component.html
@@ -19,7 +19,7 @@
             </a>
         </li>
         <li *ngIf="getConfigDownloadResultFormat('download_vo')" role="menuitem" [class.disabled]="!sampRegistered">
-            <a class="dropdown-item" [class.disabled]="!sampRegistered" (click)="broadcast.emit()">
+            <a class="dropdown-item" [class.disabled]="!sampRegistered" (click)="broadcastResult()">
                 <span class="fas fa-broadcast-tower"></span> Broadcast VOtable
             </a>
         </li>
diff --git a/client/src/app/instance/search/components/result/datatable-actions.component.ts b/client/src/app/instance/search/components/result/datatable-actions.component.ts
index 8b3b7ef203949153afbbb251fed913f9adf6face..58331ce19f0053cab31fb29de583b7c9775b91b3 100644
--- a/client/src/app/instance/search/components/result/datatable-actions.component.ts
+++ b/client/src/app/instance/search/components/result/datatable-actions.component.ts
@@ -17,8 +17,7 @@ export class DatatableActionsComponent {
     @Input() coneSearch: ConeSearch;
     @Input() dataLength: number;
     @Input() sampRegistered: boolean;
-    @Output() broadcast: EventEmitter<string> = new EventEmitter();
-    @Output() startTaskCreateResult: EventEmitter<{ format: string, selectedData: boolean }> = new EventEmitter();
+    @Output() startTaskCreateResult: EventEmitter<{ format: string, selectedData: boolean, broadcastVo: boolean }> = new EventEmitter();
     @Output() startTaskCreateArchive: EventEmitter<{ selectedData: boolean }> = new EventEmitter();
 
     /**
@@ -44,10 +43,19 @@ export class DatatableActionsComponent {
     downloadResult(format: string) {
         this.startTaskCreateResult.emit({
             format,
-            selectedData: true
+            selectedData: true,
+            broadcastVo: false
         });
     }
 
+    broadcastResult() {
+        this.startTaskCreateResult.emit({
+            format: 'votable',
+            selectedData: true,
+            broadcastVo: true
+        })
+    }
+
     downloadArchive() {
         this.startTaskCreateArchive.emit({
             selectedData: true
diff --git a/client/src/app/instance/search/components/result/datatable-tab.component.ts b/client/src/app/instance/search/components/result/datatable-tab.component.ts
index 2f4e3475b628d1e746d03f88ec93c27d5eef1cd5..97335f09355bdbb67eacec67bdd813809d9bcde3 100644
--- a/client/src/app/instance/search/components/result/datatable-tab.component.ts
+++ b/client/src/app/instance/search/components/result/datatable-tab.component.ts
@@ -40,7 +40,7 @@ export class DatatableTabComponent {
     @Output() addSelectedData: EventEmitter<number | string> = new EventEmitter();
     @Output() deleteSelectedData: EventEmitter<number | string> = new EventEmitter();
     @Output() broadcast: EventEmitter<string> = new EventEmitter();
-    @Output() startTaskCreateResult: EventEmitter<{ format: string, selectedData: boolean }> = new EventEmitter();
+    @Output() startTaskCreateResult: EventEmitter<{ format: string, selectedData: boolean, broadcastVo: boolean }> = new EventEmitter();
     @Output() startTaskCreateArchive: EventEmitter<{ selectedData: boolean }> = new EventEmitter();
     @Output() downloadFile: EventEmitter<{url: string, fileId: string, datasetName: string, filename: string}> = new EventEmitter();
 }
diff --git a/client/src/app/instance/search/components/result/download.component.html b/client/src/app/instance/search/components/result/download.component.html
index 0c9c15a510fa3b62b7405b882a5d30a4068808dd..cf29bc5791b3e7269884b54e8d9abafbe68ca7a2 100644
--- a/client/src/app/instance/search/components/result/download.component.html
+++ b/client/src/app/instance/search/components/result/download.component.html
@@ -30,7 +30,7 @@
                         <span class="fas fa-file"></span> VOtable
                     </a>
                     &nbsp;
-                    <button *ngIf="getConfigDownloadResultFormat('download_vo')" [disabled]="!sampRegistered" (click)="downloadResult('votable')" class="btn btn-outline-primary" title="Broadcast samp votable">
+                    <button *ngIf="getConfigDownloadResultFormat('download_vo')" [disabled]="!sampRegistered" (click)="broadcastResult()" class="btn btn-outline-primary" title="Broadcast samp votable">
                         <span class="fas fa-broadcast-tower"></span> Broadcast VOtable
                     </button>
                 </div>
diff --git a/client/src/app/instance/search/components/result/download.component.ts b/client/src/app/instance/search/components/result/download.component.ts
index d5a16313c639a946103d4752bddaf6f2993ca21c..42f3584a1a361104e1ed9032a2899fa6fdcfc3f0 100644
--- a/client/src/app/instance/search/components/result/download.component.ts
+++ b/client/src/app/instance/search/components/result/download.component.ts
@@ -29,7 +29,7 @@ export class DownloadComponent {
     @Input() dataLength: number;
     @Input() sampRegistered: boolean;
     @Output() broadcast: EventEmitter<string> = new EventEmitter();
-    @Output() startTaskCreateResult: EventEmitter<{ format: string, selectedData: boolean }> = new EventEmitter();
+    @Output() startTaskCreateResult: EventEmitter<{ format: string, selectedData: boolean, broadcastVo: boolean }> = new EventEmitter();
     @Output() startTaskCreateArchive: EventEmitter<{ selectedData: boolean }> = new EventEmitter();
 
     /**
@@ -64,10 +64,19 @@ export class DownloadComponent {
     downloadResult(format: string) {
         this.startTaskCreateResult.emit({
             format,
-            selectedData: false
+            selectedData: false,
+            broadcastVo: false
         });
     }
 
+    broadcastResult() {
+        this.startTaskCreateResult.emit({
+            format: 'votable',
+            selectedData: false,
+            broadcastVo: true
+        })
+    }
+
     downloadArchive() {
         this.startTaskCreateArchive.emit({
             selectedData: false
diff --git a/client/src/app/instance/search/components/result/index.ts b/client/src/app/instance/search/components/result/index.ts
index 4fa8d96abe8417aebb5a490ea60e9744f7616cc6..b39de14f79a0d38682f33ddfb074ded06e17955a 100644
--- a/client/src/app/instance/search/components/result/index.ts
+++ b/client/src/app/instance/search/components/result/index.ts
@@ -1,9 +1,8 @@
 import { DatatableTabComponent } from './datatable-tab.component';
 import { DownloadComponent } from './download.component';
 import { ReminderComponent } from './reminder.component';
-import { SampComponent } from './samp.component';
 import { UrlDisplayComponent } from './url-display.component';
-import { DatatableComponent } from './datatable.component';
+import { DatatableComponent } from './datatable.component';
 import { DatatableActionsComponent } from './datatable-actions.component';
 import { DownloadFileTabComponent } from './download-file-tab.component';
 import { rendererComponents } from './renderer';
@@ -12,7 +11,6 @@ export const resultComponents = [
     DatatableTabComponent,
     DownloadComponent,
     ReminderComponent,
-    SampComponent,
     UrlDisplayComponent,
     DatatableComponent,
     DatatableActionsComponent,
diff --git a/client/src/app/instance/search/components/result/samp.component.html b/client/src/app/instance/search/components/result/samp.component.html
deleted file mode 100644
index 9970bd3d96b083b4fd957ec3d7970fb8c28c9c9c..0000000000000000000000000000000000000000
--- a/client/src/app/instance/search/components/result/samp.component.html
+++ /dev/null
@@ -1,32 +0,0 @@
-<accordion *ngIf="isSampActivated()" [isAnimated]="true">
-    <accordion-group #ag [isOpen]="isSampOpened()" [panelClass]="'custom-accordion'" class="my-2">
-        <button class="btn btn-link btn-block clearfix" accordion-heading>
-            <span class="pull-left float-left">
-                <span [style.color]="getColor()">
-                    <span class="fas fa-circle"></span>
-                </span> SAMP access
-                &nbsp;
-                <span *ngIf="ag.isOpen">
-                    <span class="fas fa-chevron-up"></span>
-                </span>
-                <span *ngIf="!ag.isOpen">
-                    <span class="fas fa-chevron-down"></span>
-                </span>
-            </span>
-        </button>
-        <div>
-            <div class="row">
-                <p *ngIf="!sampRegistered" class="lead">
-                    You are not connected to a SAMP-hub 
-                </p>
-                <p *ngIf="sampRegistered" class="lead">
-                    You are connected to a SAMP-hub 
-                </p>
-            </div>
-            <div class="row">
-                <button *ngIf="!sampRegistered" (click)="sampRegister.emit()" class="btn btn-outline-primary">Try to register</button>
-                <button *ngIf="sampRegistered" (click)="sampUnregister.emit()" class="btn btn-outline-primary">Unregister</button>
-            </div>
-        </div>
-    </accordion-group>
-</accordion>
diff --git a/client/src/app/instance/search/components/result/samp.component.spec.ts b/client/src/app/instance/search/components/result/samp.component.spec.ts
deleted file mode 100644
index fd6f128fe38eb7a1600e348950a5a45001da36ee..0000000000000000000000000000000000000000
--- a/client/src/app/instance/search/components/result/samp.component.spec.ts
+++ /dev/null
@@ -1,183 +0,0 @@
-import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
-
-import { AccordionModule } from 'ngx-bootstrap/accordion';
-
-import { SampComponent } from './samp.component';
-
-describe('[Instance][Search][Component][Result] SampComponent', () => {
-    let component: SampComponent;
-    let fixture: ComponentFixture<SampComponent>;
-
-    beforeEach(() => {
-        TestBed.configureTestingModule({
-            declarations: [SampComponent],
-            imports: [
-                AccordionModule.forRoot(),
-                BrowserAnimationsModule
-            ]
-        });
-        fixture = TestBed.createComponent(SampComponent);
-        component = fixture.componentInstance;
-    });
-
-    it('should create the component', () => {
-        expect(component).toBeTruthy();
-    });
-
-    it('#isSampActivated() should return if SAMP has to be enabled or not', () => {
-        component.datasetList = [
-            {
-                name: 'myDataset',
-                table_ref: 'table',
-                label: 'my dataset',
-                description: 'This is my dataset',
-                display: 1,
-                data_path: '/path',
-                survey_name: 'mySurvey',
-                id_dataset_family: 1,
-                public: true,
-                full_data_path: '/data/path',
-                info_survey_enabled: true,
-                info_survey_label: 'More about this survey',
-                cone_search_enabled: true,
-                cone_search_opened: true,
-                cone_search_column_ra: 1,
-                cone_search_column_dec: 2,
-                download_enabled: true,
-                download_opened: true,
-                download_csv: true,
-                download_ascii: true,
-                download_vo: true,
-                download_archive: true,
-                summary_enabled: true,
-                summary_opened: true,
-                server_link_enabled: false,
-                server_link_opened: true,
-                samp_enabled: false,
-                samp_opened: false,
-                datatable_enabled: true,
-                datatable_opened: true,
-                datatable_selectable_rows: true
-            },
-            {
-                name: 'anotherDataset',
-                table_ref: 'table',
-                label: 'another dataset',
-                description: 'This is another dataset',
-                display: 1,
-                data_path: '/path',
-                survey_name: 'mySurvey',
-                id_dataset_family: 1,
-                public: true,
-                full_data_path: '/data/path',
-                info_survey_enabled: true,
-                info_survey_label: 'More about this survey',
-                cone_search_enabled: true,
-                cone_search_opened: true,
-                cone_search_column_ra: 1,
-                cone_search_column_dec: 2,
-                download_enabled: true,
-                download_opened: true,
-                download_csv: true,
-                download_ascii: true,
-                download_vo: true,
-                download_archive: true,
-                summary_enabled: true,
-                summary_opened: true,
-                server_link_enabled: true,
-                server_link_opened: true,
-                samp_enabled: true,
-                samp_opened: true,
-                datatable_enabled: true,
-                datatable_opened: true,
-                datatable_selectable_rows: true
-            }
-        ];
-        component.datasetSelected = 'myDataset';
-        expect(component.isSampActivated()).toBeFalsy();
-        component.datasetSelected = 'anotherDataset';
-        expect(component.isSampActivated()).toBeTruthy();
-    });
-
-    it('#isSampOpened() should return if URL tab has to be opened or not', () => {
-        component.datasetList = [
-            {
-                name: 'myDataset',
-                table_ref: 'table',
-                label: 'my dataset',
-                description: 'This is my dataset',
-                display: 1,
-                data_path: '/path',
-                survey_name: 'mySurvey',
-                id_dataset_family: 1,
-                public: true,
-                full_data_path: '/data/path',
-                info_survey_enabled: true,
-                info_survey_label: 'More about this survey',
-                cone_search_enabled: true,
-                cone_search_opened: true,
-                cone_search_column_ra: 1,
-                cone_search_column_dec: 2,
-                download_enabled: true,
-                download_opened: true,
-                download_csv: true,
-                download_ascii: true,
-                download_vo: true,
-                download_archive: true,
-                summary_enabled: true,
-                summary_opened: true,
-                server_link_enabled: false,
-                server_link_opened: false,
-                samp_enabled: false,
-                samp_opened: false,
-                datatable_enabled: true,
-                datatable_opened: true,
-                datatable_selectable_rows: true
-            },
-            {
-                name: 'anotherDataset',
-                table_ref: 'table',
-                label: 'another dataset',
-                description: 'This is another dataset',
-                display: 1,
-                data_path: '/path',
-                survey_name: 'mySurvey',
-                id_dataset_family: 1,
-                public: true,
-                full_data_path: '/data/path',
-                info_survey_enabled: true,
-                info_survey_label: 'More about this survey',
-                cone_search_enabled: true,
-                cone_search_opened: true,
-                cone_search_column_ra: 1,
-                cone_search_column_dec: 2,
-                download_enabled: true,
-                download_opened: true,
-                download_csv: true,
-                download_ascii: true,
-                download_vo: true,
-                download_archive: true,
-                summary_enabled: true,
-                summary_opened: true,
-                server_link_enabled: true,
-                server_link_opened: true,
-                samp_enabled: true,
-                samp_opened: true,
-                datatable_enabled: true,
-                datatable_opened: true,
-                datatable_selectable_rows: true
-            }
-        ];
-        component.datasetSelected = 'myDataset';
-        expect(component.isSampOpened()).toBeFalsy();
-        component.datasetSelected = 'anotherDataset';
-        expect(component.isSampOpened()).toBeTruthy();
-    });
-
-    it('#getColor() should return color button depending on SAMP registered or not', () => {
-        expect(component.getColor()).toEqual('red');
-        component.sampRegistered = true;
-        expect(component.getColor()).toEqual('green');
-    });
-});
diff --git a/client/src/app/instance/search/components/result/samp.component.ts b/client/src/app/instance/search/components/result/samp.component.ts
deleted file mode 100644
index be61e1c985d4eff3f07d4019dec2a7cb195d5a98..0000000000000000000000000000000000000000
--- a/client/src/app/instance/search/components/result/samp.component.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-/**
- * This file is part of Anis Client.
- *
- * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
- *
- * For the full copyright and license information, please view the LICENSE
- * file that was distributed with this source code.
- */
-
-import { Component, Input, ChangeDetectionStrategy, Output, EventEmitter } from '@angular/core';
-
-import { Dataset } from 'src/app/metamodel/models';
-
-/**
- * @class
- * @classdesc Samp component.
- */
-@Component({
-    selector: 'app-samp',
-    templateUrl: 'samp.component.html',
-    changeDetection: ChangeDetectionStrategy.OnPush
-})
-export class SampComponent {
-    @Input() datasetSelected: string;
-    @Input() datasetList: Dataset[];
-    @Input() sampRegistered: boolean;
-    @Output() sampRegister: EventEmitter<{}> = new EventEmitter();
-    @Output() sampUnregister: EventEmitter<{}> = new EventEmitter();
-
-    /**
-     * Checks if SAMP has to be display.
-     *
-     * @return boolean
-     */
-    isSampActivated(): boolean {
-        return this.datasetList.find(d => d.name === this.datasetSelected).samp_enabled;
-    }
-
-    /**
-     * Checks if SAMP tab has to be opened.
-     *
-     * @return boolean
-     */
-    isSampOpened(): boolean {
-        return this.datasetList.find(d => d.name === this.datasetSelected).samp_opened;
-    }
-
-    /**
-     * Returns SAMP color button.
-     *
-     * @return boolean
-     */
-    getColor(): string {
-        if (this.sampRegistered) return 'green';
-        return 'red';
-    }
-}
diff --git a/client/src/app/instance/search/containers/result.component.html b/client/src/app/instance/search/containers/result.component.html
index d06e9f7f5d38fe71eb6878a08d112f32a7426ef1..3a1eabae5af2f0acd198072acf6a0cb04f590037 100644
--- a/client/src/app/instance/search/containers/result.component.html
+++ b/client/src/app/instance/search/containers/result.component.html
@@ -25,6 +25,18 @@
                     selected with <span class="font-weight-bold">{{ dataLength | async }}</span> objects found.
                 </div>
             </div>
+            <div *ngIf="sampEnabled()" class="jumbotron mb-4 py-4">
+                <div class="lead">
+                    <ng-container *ngIf="!(sampRegistered | async)">
+                        You are not connected to a SAMP-hub
+                        <button (click)="sampRegister()" class="btn btn-outline-primary">Try to register</button>
+                    </ng-container>
+                    <ng-container *ngIf="(sampRegistered | async)">
+                        You are connected to a SAMP-hub
+                        <button (click)="sampUnregister()" class="btn btn-outline-primary">Unregister</button>
+                    </ng-container>
+                </div>
+            </div>
             <app-download-file-tab
                 *ngIf="(downloadedFiles | async).length > 0"
                 [downloadedFiles]="downloadedFiles | async">
@@ -52,13 +64,6 @@
                 [coneSearch]="coneSearch | async"
                 [outputList]="outputList | async">
             </app-reminder>
-            <app-samp
-                [datasetSelected]="datasetSelected | async"
-                [datasetList]="datasetList | async"
-                [sampRegistered]="sampRegistered | async"
-                (sampRegister)="sampRegister()"
-                (sampUnregister)="sampUnregister()">
-            </app-samp>
             <app-url-display
                 [datasetSelected]="datasetSelected | async"
                 [datasetList]="datasetList | async"
diff --git a/client/src/app/instance/search/containers/result.component.ts b/client/src/app/instance/search/containers/result.component.ts
index cc058ea450f4445bd295363a7fe2b2a25dee5f34..8d93cdbae7950f00c8b9e10c1b9fe5e0f054b688 100644
--- a/client/src/app/instance/search/containers/result.component.ts
+++ b/client/src/app/instance/search/containers/result.component.ts
@@ -12,14 +12,15 @@ import { Component } from '@angular/core';
 import { Store } from '@ngrx/store';
 import { Observable, Subscription } from 'rxjs';
 
+import { AppConfigService } from 'src/app/app-config.service';
 import { AbstractSearchComponent } from './abstract-search.component';
 import { Pagination, DownloadFile } from '../../store/models';
 import { Instance } from 'src/app/metamodel/models';
 import * as instanceSelector from 'src/app/metamodel/selectors/instance.selector';
 import * as searchActions from '../../store/actions/search.actions';
 import * as searchSelector from '../../store/selectors/search.selector';
-import * as sampActions from '../../store/actions/samp.actions';
-import * as sampSelector from '../../store/selectors/samp.selector';
+import * as sampActions from 'src/app/samp/samp.actions';
+import * as sampSelector from 'src/app/samp/samp.selector';
 import * as downloadFileActions from '../../store/actions/download-file.actions';
 import * as downloadFileSelector from '../../store/selectors/download-file.selector';
 
@@ -47,7 +48,7 @@ export class ResultComponent extends AbstractSearchComponent {
     public downloadedFiles: Observable<DownloadFile[]>;
     public pristineSubscription: Subscription;
 
-    constructor(protected store: Store<{ }>) {
+    constructor(protected store: Store<{ }>, private appConfig: AppConfigService) {
         super(store);
         this.instance = store.select(instanceSelector.selectInstanceByRouteName);
         this.dataLength = this.store.select(searchSelector.selectDataLength);
@@ -74,6 +75,10 @@ export class ResultComponent extends AbstractSearchComponent {
         });
     }
 
+    sampEnabled() {
+        return this.appConfig.sampEnabled;
+    }
+
     /**
      * Dispatches action to register to SAMP.
      */
@@ -138,7 +143,7 @@ export class ResultComponent extends AbstractSearchComponent {
      *
      * @param string format - Info about result format
      */
-    startTaskCreateResult(event: { format: string, selectedData: boolean }) {
+    startTaskCreateResult(event: { format: string, selectedData: boolean, broadcastVo: boolean }) {
         this.store.dispatch(downloadFileActions.startTaskCreateResult(event));
     }
 
diff --git a/client/src/app/instance/store/actions/download-file.actions.ts b/client/src/app/instance/store/actions/download-file.actions.ts
index 8368ed9207b145ecd1970f5d63569c06afd35270..60fefb6f1cadd470066f5b081b2afcf553d23a93 100644
--- a/client/src/app/instance/store/actions/download-file.actions.ts
+++ b/client/src/app/instance/store/actions/download-file.actions.ts
@@ -9,10 +9,10 @@
 
 import { createAction, props } from '@ngrx/store';
 
-export const startTaskCreateResult = createAction('[File] Start Task Create Result', props<{ format: string, selectedData: boolean }>());
-export const startTaskCreateResultSuccess = createAction('[File] Start Task Create Result Success', props<{ fileId: string, datasetName: string, filename: string }>());
+export const startTaskCreateResult = createAction('[File] Start Task Create Result', props<{ format: string, selectedData: boolean, broadcastVo: boolean }>());
+export const startTaskCreateResultSuccess = createAction('[File] Start Task Create Result Success', props<{ fileId: string, datasetName: string, filename: string, broadcastVo: boolean }>());
 export const startTaskCreateResultFail = createAction('[File] Start Task Create Result Fail');
-export const isResultAvailable = createAction('[File] Is Result Available', props<{ fileId: string, datasetName: string, filename: string }>());
+export const isResultAvailable = createAction('[File] Is Result Available', props<{ fileId: string, datasetName: string, filename: string, broadcastVo: boolean }>());
 export const isResultAvailableFail = createAction('[File] Is Result Available Fail');
 
 export const startTaskCreateArchive = createAction('[File] Start Task Create Archive', props<{ selectedData: boolean }>());
diff --git a/client/src/app/instance/store/effects/download-file.effects.ts b/client/src/app/instance/store/effects/download-file.effects.ts
index b7caa91165f2ff0a6bc6144714109e2b8c1fe140..1cb58cd4d6cbd3b7d37cb60a7567f9990e503e24 100644
--- a/client/src/app/instance/store/effects/download-file.effects.ts
+++ b/client/src/app/instance/store/effects/download-file.effects.ts
@@ -19,6 +19,7 @@ import { ToastrService } from 'ngx-toastr';
 import { AppConfigService } from 'src/app/app-config.service';
 import { DownloadFileService } from '../services/download-file.service';
 import * as downloadFileActions from '../actions/download-file.actions';
+import * as sampActions from 'src/app/samp/samp.actions';
 import * as searchSelector from '../selectors/search.selector';
 import * as attributeSelector from 'src/app/metamodel/selectors/attribute.selector';
 import * as coneSearchSelector from '../selectors/cone-search.selector';
@@ -61,7 +62,8 @@ export class DownloadFileEffects {
                         map((response) => downloadFileActions.startTaskCreateResultSuccess({
                             fileId: response.file_id,
                             filename: response.file_name,
-                            datasetName: currentDataset
+                            datasetName: currentDataset,
+                            broadcastVo: action.broadcastVo
                         })),
                         catchError(() => of(downloadFileActions.startTaskCreateResultFail()))
                     )
@@ -94,17 +96,28 @@ export class DownloadFileEffects {
             ofType(downloadFileActions.isResultAvailable),
             switchMap(action => this.downloadFileService.isResultAvailable(action.fileId)
                 .pipe(
-                    map(result => {
+                    switchMap(result => {
                         if (result.file_is_available) {
                             this.kill$[action.fileId].next({});
                             this.kill$[action.fileId].unsubscribe();
-                            return downloadFileActions.startsDownloadingFile({
-                                fileId: action.fileId,
-                                filename: action.filename,
-                                url: `${this.config.apiUrl}/download-result/${action.datasetName}/${action.fileId}`
-                            });
+                            if (action.broadcastVo) {
+                                return [
+                                    sampActions.broadcastVotable({
+                                        url: `${this.config.apiUrl}/download-result/${action.datasetName}/${action.fileId}`
+                                    }),
+                                    downloadFileActions.fileDownloaded({ fileId: action.fileId })
+                                ];
+                            } else {
+                                return [
+                                    downloadFileActions.startsDownloadingFile({
+                                        fileId: action.fileId,
+                                        filename: action.filename,
+                                        url: `${this.config.apiUrl}/download-result/${action.datasetName}/${action.fileId}`
+                                    })
+                                ];
+                            }
                         } else {
-                            return { type: '[No Action] Is Result Available' };
+                            return [{ type: '[No Action] Is Result Available' }];
                         }
                     }),
                     catchError(() => of(downloadFileActions.isResultAvailableFail()))
diff --git a/client/src/app/instance/store/effects/index.ts b/client/src/app/instance/store/effects/index.ts
index 18cb99de4d7126d13194355146ddacf39b3c8ae5..ddaa3d86df6a14dc0dababa0aa9fafafd4dad401 100644
--- a/client/src/app/instance/store/effects/index.ts
+++ b/client/src/app/instance/store/effects/index.ts
@@ -1,4 +1,3 @@
-import { SampEffects } from './samp.effects';
 import { SearchEffects } from './search.effects';
 import { SearchMultipleEffects } from './search-multiple.effects';
 import { ConeSearchEffects } from './cone-search.effects';
@@ -7,7 +6,6 @@ import { SvomJsonKwEffects } from './svom-json-kw.effects';
 import { DownloadFileEffects } from './download-file.effects';
 
 export const instanceEffects = [
-    SampEffects,
     SearchEffects,
     SearchMultipleEffects,
     ConeSearchEffects,
diff --git a/client/src/app/instance/store/services/index.ts b/client/src/app/instance/store/services/index.ts
index d70ddbf82870dc1059472f410111eb4979b00052..4f4c2847d6d9b98de06b4daef5509ffb8e82a3ba 100644
--- a/client/src/app/instance/store/services/index.ts
+++ b/client/src/app/instance/store/services/index.ts
@@ -1,5 +1,4 @@
 import { SearchService } from './search.service';
-import { SampService } from './samp.service';
 import { ConeSearchService } from './cone-search.service';
 import { DetailService } from './detail.service';
 import { SvomJsonKwService } from './svom-json-kw.service';
@@ -7,7 +6,6 @@ import { DownloadFileService } from './download-file.service';
 
 export const instanceServices = [
     SearchService,
-    SampService,
     ConeSearchService,
     DetailService,
     SvomJsonKwService,
diff --git a/client/src/app/instance/store/actions/samp.actions.ts b/client/src/app/samp/samp.actions.ts
similarity index 100%
rename from client/src/app/instance/store/actions/samp.actions.ts
rename to client/src/app/samp/samp.actions.ts
diff --git a/client/src/app/instance/store/effects/samp.effects.spec.ts b/client/src/app/samp/samp.effects.spec.ts
similarity index 97%
rename from client/src/app/instance/store/effects/samp.effects.spec.ts
rename to client/src/app/samp/samp.effects.spec.ts
index 1220db80bd3e8f6d74e2532069cc8e20df1dba87..b2aa420b00418a72d7638d7d539ef9b7439a4e7a 100644
--- a/client/src/app/instance/store/effects/samp.effects.spec.ts
+++ b/client/src/app/samp/samp.effects.spec.ts
@@ -7,8 +7,8 @@ import { cold, hot } from 'jasmine-marbles';
 import { ToastrService } from 'ngx-toastr';
 
 import { SampEffects } from './samp.effects';
-import { SampService } from '../services/samp.service';
-import * as sampActions from '../actions/samp.actions';
+import { SampService } from './samp.service';
+import * as sampActions from './samp.actions';
 
 describe('[Instance][Store] SampEffects', () => {
     let actions = new Observable();
diff --git a/client/src/app/instance/store/effects/samp.effects.ts b/client/src/app/samp/samp.effects.ts
similarity index 69%
rename from client/src/app/instance/store/effects/samp.effects.ts
rename to client/src/app/samp/samp.effects.ts
index 6d685853788c586e1bbc8845d8e794c48c0087fa..7ddb3e71ffc356011548ecc6b29a3de4e32d90de 100644
--- a/client/src/app/instance/store/effects/samp.effects.ts
+++ b/client/src/app/samp/samp.effects.ts
@@ -9,13 +9,17 @@
 
 import { Injectable } from '@angular/core';
 
-import { Actions, createEffect, ofType } from '@ngrx/effects';
-import { of } from 'rxjs';
+import { Store } from '@ngrx/store';
+import { Actions, createEffect, ofType, concatLatestFrom } from '@ngrx/effects';
+import { of, from } from 'rxjs';
 import { map, tap, mergeMap, catchError } from 'rxjs/operators';
+
+import { KeycloakService } from 'keycloak-angular';
 import { ToastrService } from 'ngx-toastr';
 
-import { SampService } from '../services/samp.service';
-import * as sampActions from '../actions/samp.actions';
+import { SampService } from './samp.service';
+import * as sampActions from './samp.actions';
+import * as authSelector from 'src/app/auth/auth.selector';
 
 /**
  * @class
@@ -23,7 +27,6 @@ import * as sampActions from '../actions/samp.actions';
  */
 @Injectable()
 export class SampEffects {
-
     /**
      * Calls actions to register.
      */
@@ -80,8 +83,16 @@ export class SampEffects {
     broadcastVotable$ = createEffect(() =>
         this.actions$.pipe(
             ofType(sampActions.broadcastVotable),
-            tap(action => {
-                this.sampService.broadcast('table.load.votable', action.url)
+            concatLatestFrom(() => this.store.select(authSelector.selectIsAuthenticated)),
+            tap(([action, isAuthenticated]) => {
+                if (isAuthenticated) {
+                    console.log('Authenticated');
+                    this.keycloak.getToken().then(token => {
+                        this.sampService.broadcast('table.load.votable', `${action.url}?token=${token}`);
+                    });
+                } else {
+                    this.sampService.broadcast('table.load.votable', action.url);
+                }
             })
         ),
         { dispatch: false }
@@ -90,6 +101,8 @@ export class SampEffects {
     constructor(
         private actions$: Actions,
         private sampService: SampService,
+        private store: Store<{ }>,
+        private keycloak: KeycloakService,
         private toastr: ToastrService
     ) {}
 }
diff --git a/client/src/app/samp/samp.module.ts b/client/src/app/samp/samp.module.ts
new file mode 100644
index 0000000000000000000000000000000000000000..59f9f5850eec66df1ddc47e610c0b24ae2547bc6
--- /dev/null
+++ b/client/src/app/samp/samp.module.ts
@@ -0,0 +1,28 @@
+/**
+ * This file is part of Anis Client.
+ *
+ * @copyright Laboratoire d'Astrophysique de Marseille / CNRS
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+import { NgModule } from '@angular/core';
+
+import { StoreModule } from '@ngrx/store';
+import { EffectsModule } from '@ngrx/effects';
+
+import { sampReducer } from './samp.reducer';
+import { SampEffects } from './samp.effects';
+import { SampService } from './samp.service';
+
+@NgModule({
+    imports: [
+        StoreModule.forFeature('samp', sampReducer),
+        EffectsModule.forFeature([ SampEffects ])
+    ],
+    providers: [
+        SampService
+    ]
+})
+export class SampModule { }
diff --git a/client/src/app/instance/store/reducers/samp.reducer.spec.ts b/client/src/app/samp/samp.reducer.spec.ts
similarity index 96%
rename from client/src/app/instance/store/reducers/samp.reducer.spec.ts
rename to client/src/app/samp/samp.reducer.spec.ts
index d8cec00d47fae1f75481f50c7bffbfeafeaade34..0fab3a66b4750934f88c3cf9ad26ff86aea9d9bd 100644
--- a/client/src/app/instance/store/reducers/samp.reducer.spec.ts
+++ b/client/src/app/samp/samp.reducer.spec.ts
@@ -1,7 +1,7 @@
 import { Action } from '@ngrx/store';
 
 import * as fromSamp from './samp.reducer';
-import * as sampActions from '../actions/samp.actions';
+import * as sampActions from './samp.actions';
 
 describe('[Instance][Store] Samp reducer', () => {
     it('unknown action should return the default state', () => {
diff --git a/client/src/app/instance/store/reducers/samp.reducer.ts b/client/src/app/samp/samp.reducer.ts
similarity index 93%
rename from client/src/app/instance/store/reducers/samp.reducer.ts
rename to client/src/app/samp/samp.reducer.ts
index f16136d25d96e7789d838d8da2462a14424c37ec..96c5431864fe11a8e3271c7621290a3d1f9c0e55 100644
--- a/client/src/app/instance/store/reducers/samp.reducer.ts
+++ b/client/src/app/samp/samp.reducer.ts
@@ -9,7 +9,7 @@
 
 import { createReducer, on } from '@ngrx/store';
 
-import * as sampActions from '../actions/samp.actions';
+import * as sampActions from './samp.actions';
 
 /**
  * Interface for samp state.
diff --git a/client/src/app/instance/store/selectors/samp.selector.spec.ts b/client/src/app/samp/samp.selector.spec.ts
similarity index 84%
rename from client/src/app/instance/store/selectors/samp.selector.spec.ts
rename to client/src/app/samp/samp.selector.spec.ts
index ab8f44b37c53981db9be4ce9c76c9d99a74a1f58..32d0572c6207f10354c41e7fcf8b12d21f31bb12 100644
--- a/client/src/app/instance/store/selectors/samp.selector.spec.ts
+++ b/client/src/app/samp/samp.selector.spec.ts
@@ -1,5 +1,5 @@
 import * as sampSelector from './samp.selector';
-import * as fromSamp from '../reducers/samp.reducer';
+import * as fromSamp from './samp.reducer';
 
 describe('[Instance][Store] Samp selector', () => {
     it('should get registered', () => {
diff --git a/client/src/app/instance/store/selectors/samp.selector.ts b/client/src/app/samp/samp.selector.ts
similarity index 52%
rename from client/src/app/instance/store/selectors/samp.selector.ts
rename to client/src/app/samp/samp.selector.ts
index d485b19f91a13a881a78ae04896e117a2b9dc7f5..410c723c8bdea8d2e5062c1633a8ca5d9d9050aa 100644
--- a/client/src/app/instance/store/selectors/samp.selector.ts
+++ b/client/src/app/samp/samp.selector.ts
@@ -7,17 +7,13 @@
  * file that was distributed with this source code.
  */
 
-import { createSelector } from '@ngrx/store';
+import { createSelector, createFeatureSelector  } from '@ngrx/store';
 
-import * as reducer from '../../instance.reducer';
-import * as fromSamp from '../reducers/samp.reducer';
+import * as fromSamp from './samp.reducer';
 
-export const selectSampState = createSelector(
-    reducer.getInstanceState,
-    (state: reducer.State) => state.samp
-);
+export const selectAuthState = createFeatureSelector<fromSamp.State>('samp');
 
 export const selectRegistered = createSelector(
-    selectSampState,
+    selectAuthState,
     fromSamp.selectRegistered
 );
diff --git a/client/src/app/instance/store/services/samp.service.ts b/client/src/app/samp/samp.service.ts
similarity index 97%
rename from client/src/app/instance/store/services/samp.service.ts
rename to client/src/app/samp/samp.service.ts
index 3dea465b139563c25674109a46b0d6cc5b179324..a8ecc5796aa3c2a0dca2233499bb73fec763f060 100644
--- a/client/src/app/instance/store/services/samp.service.ts
+++ b/client/src/app/samp/samp.service.ts
@@ -23,7 +23,14 @@ declare var samp: any;
 export class SampService {
     private connector = null;
     
-    constructor(private config: AppConfigService) {
+    constructor(private config: AppConfigService) { }
+
+    /**
+     * Register to Samp.
+     *
+     * @return Observable<any>
+     */
+    register(): Observable<any> {
         let baseUrl = `${window.location.protocol}//${window.location.host}`;
         if (this.config.baseHref !== '/') {
             baseUrl += this.config.baseHref;
@@ -37,14 +44,7 @@ export class SampService {
             "samp.icon.url": `${baseUrl}/assets/cesam_anis40.png`
         };
         this.connector = new samp.Connector("anis-client", meta);
-    }
 
-    /**
-     * Register to Samp.
-     *
-     * @return Observable<any>
-     */
-    register(): Observable<any> {
         return new Observable(observer => {
             samp.register(this.connector.name, (conn) => {
                 this.connector.setConnection(conn);
diff --git a/docker-compose.yml b/docker-compose.yml
index 06b8074d7e6be4d1320d0781535d17d99d006895..eb381ed7d8dee10fa27881a1aa850ecef5d7f806 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -33,10 +33,11 @@ services:
             LOGGER_LEVEL: "debug"
             SERVICES_URL: "http://localhost:5000"
             BASE_HREF: "/"
+            SAMP_ENABLED: 1
             SSO_AUTH_URL: "http://localhost:8180/auth"
             SSO_REALM: "anis"
             SSO_CLIENT_ID: "anis-client"
-            TOKEN_ENABLED: 0
+            TOKEN_ENABLED: 1
             TOKEN_JWKS_URL: "http://keycloak:8180/auth/realms/anis/protocol/openid-connect/certs"
             TOKEN_ADMIN_ROLES: anis_admin,superuser
             RMQ_HOST: rmq
diff --git a/server/app/settings.php b/server/app/settings.php
index e062e3ef440da113b8ce0268cb6f3f1faa6b1cd3..5ceab1a828e734839f433086ea9b782ac2001a03 100644
--- a/server/app/settings.php
+++ b/server/app/settings.php
@@ -35,6 +35,7 @@ return [
     ],
     'services_url' => getenv('SERVICES_URL'),
     'base_href' => getenv('BASE_HREF'),
+    'samp_enabled' => getenv('SAMP_ENABLED'),
     'sso' => [
         'auth_url' => getenv('SSO_AUTH_URL'),
         'realm' => getenv('SSO_REALM'),
diff --git a/server/src/Action/ClientSettingsAction.php b/server/src/Action/ClientSettingsAction.php
index 9ccc6f48de67f3a928bdc060c7cd128010246f6e..5b84798e34a73373b5ab6dd75a0c194c04b92dfe 100644
--- a/server/src/Action/ClientSettingsAction.php
+++ b/server/src/Action/ClientSettingsAction.php
@@ -52,6 +52,7 @@ final class ClientSettingsAction
         $payload = json_encode(array(
             'servicesUrl' => $this->settings['services_url'],
             'baseHref' => $this->settings['base_href'],
+            'sampEnabled' => boolval($this->settings['samp_enabled']),
             'authenticationEnabled' => boolval($this->settings['token']['enabled']),
             'ssoAuthUrl' => $this->settings['sso']['auth_url'],
             'ssoRealm' => $this->settings['sso']['realm'],