|

|

Backup Zoho Analytics folosind PowerShell


Pentru companiile care folosesc Zoho Analytics în raportare și analiză de date, asigurarea unor backup-uri regulate este esențială pentru continuitate și protecția datelor.

În acest articol îți prezint un script PowerShell avansat pe care l-am scris pentru a automatiza complet procesul de backup prin API-ul Zoho.

🔍 Ce face acest script?

✅ Se autentifică automat folosind un refresh token OAuth 2.0
✅ Accesează toate workspace-urile asociate contului Zoho Analytics
✅ Extrage doar tabelele (viewType: Table)
✅ Salvează datele în format .csv organizat pe directoare
✅ Loghează toate acțiunile și erorile într-un fișier .log


📜 Scriptul complet

# Written by
# Alexandru Ressa - 2024
# Free for commercial and personal use

$backup_path = "F:\Zoho Analytics\"
$log_path = "F:\Zoho Analytics\backup_zoho_analytics.log"


$auth_url = 'https://accounts.zoho.eu/oauth/v2/token'
$api_url = 'https://analyticsapi.zoho.eu/restapi/v2/'


$client_id = "1000.xxxxxxxxxxx"
$client_secret = "xxxxxx"
$organization_id = "xxxxxx"

$refresh_token = "1000.xxxxxxxxxx"

# Hide download progress from console
$ProgressPreference = 'SilentlyContinue'

# Helper function for LOG timestamp
function Get-TimeStamp {
    return "[{0:MM/dd/yy} {0:HH:mm:ss}]" -f (Get-Date)
}
$date = Get-Date -Format "dd.MM.yyyy"

# Set backup path as path\dd-mm-yyy\
$backup_path = $backup_path + $date + "\"

# Begin token generation from refresh
try { $Result = Invoke-RestMethod -Method Post -Uri "$($auth_url)?refresh_token=$($refresh_token)&client_id=$($client_id)&client_secret=$($client_secret)&grant_type=refresh_token" -UseBasicParsing }
catch {
    Write-Output "$(Get-TimeStamp) ERROR: $_" | Out-file $log_path -append
}

$access_token = $Result.access_token

if ($access_token) {
    Write-Output "$(Get-TimeStamp) INFO: Got access token successfully from refresh token. Continuing." | Out-file $log_path -append 
}
else {
    Write-Output "$(Get-TimeStamp) ERROR: Couldn't generate access token from refresh token. Check for ERROR logs." | Out-file $log_path -append
    Throw "The access token was not found ! Check log file for details."
}

$Headers = @{
    Authorization      = "Zoho-oauthtoken $($access_token)"
    "ZANALYTICS-ORGID" = $organization_id
}
Write-Output "DEBUG: ACCESS_TOKEN: $($access_token)"


try {
    $Result = Invoke-WebRequest -Uri ($api_url + "workspaces") -Headers $Headers -UseBasicParsing 
}
catch {
    Write-Output "$(Get-TimeStamp) ERROR: $_" | Out-file $log_path -append 
}

if ($Result.StatusCode -eq 200) {
    $content = ConvertFrom-Json $Result.Content
    $workspaces = $content.data.ownedWorkspaces

    if ($content.status -eq "success") {
        Write-Output "$(Get-TimeStamp) INFO: Got status SUCCESS from Workspaces API. Continuing." | Out-file $log_path -append 
        Write-Output "$(Get-TimeStamp) INFO: Added $(($workspaces | Measure-Object).Count) Workspaces to processing list." | Out-file $log_path -append 

        foreach ($workspace in $workspaces) {
            try {
                Start-Sleep -Seconds 10
                $Result = Invoke-WebRequest -Uri ($api_url + "workspaces/" + $workspace.workspaceId + "/views") -Headers $Headers -UseBasicParsing
            }
            catch {
                Write-Output "$(Get-TimeStamp) ERROR: $_" | Out-file $log_path -append 
            }


            if ($Result.StatusCode -eq 200) {
                $content = ConvertFrom-Json $Result.Content
                $views = $content.data.views

                if ($content.status -eq "success") {
                    Write-Output "$(Get-TimeStamp) INFO: Got status SUCCESS from Views API for workspace : $($workspace.workspaceName) - $($workspace.workspaceId). Continuing." | Out-file $log_path -append  

                    $tables = [System.Collections.ArrayList]@()

                    foreach ($view in $views) {
                        if ($view.viewType -eq "Table") {
                            $tables.Add($view)
                        }
                    }

                    Write-Output "$(Get-TimeStamp) INFO: Added $(($tables | Measure-Object).Count) tables from workspace : $($workspace.workspaceName) - $($workspace.workspaceId)" | Out-file $log_path -append

                    $download_path = $backup_path + $workspace.workspaceName + " - " + $workspace.workspaceId + "\"

                    If (!(Test-Path -PathType Container $download_path)) {
                        New-Item -ItemType Directory -Path $download_path | Out-Null
                    }


                    foreach ($table in $tables) {
                        $download_name = $download_path + $table.viewName + " - " + $table.viewId + ".csv"

                        try {
                            Start-Sleep -Seconds 1.5
                            Invoke-WebRequest ($api_url + "workspaces/$($workspace.workspaceId)/views/$($table.viewId)/data") -OutFile $download_name -Headers $Headers -UseBasicParsing
                        }
                        catch {
                            Write-Output "$(Get-TimeStamp) ERROR: $_" | Out-file $log_path -append 
                        }
                    }

                    Write-Output "$(Get-TimeStamp) INFO: Finished downloading tables from workspace : $($workspace.workspaceId)" | Out-file $log_path -append
                }
                else {
                    Write-Output ("$(Get-TimeStamp) ERROR: API reported status FAILURE for workspace ID : " + $workspace.workspaceId) | Out-file $log_path -append
                }
            }
            else {
                Write-Output ("$(Get-TimeStamp) ERROR: Could not fetch views from API for workspace ID : " + $workspace.workspaceId) | Out-file $log_path -append
            }
        }
    }
    else {
        Write-Output "$(Get-TimeStamp) ERROR: API reported status FAILURE for getting list of Workspaces" | Out-file $log_path -append
    }
    
}
else { Write-Output "$(Get-TimeStamp) ERROR: Could not fetch Workspaces from API. Check for ERROR logs above." | Out-file $log_path -append }


Write-Output "$(Get-TimeStamp) INFO: Successfully finished script completion for $($date). Check above for ERROR logs if data is not consistent." | Out-file $log_path -append

🧠 Tehnologii folosite

  • PowerShell pentru automatizare Windows-based
  • Zoho Analytics REST API v2
  • OAuth 2.0 pentru autentificare
  • Filesystem Structuring pentru backup organizat pe dată și workspace

🔐 Autentificare prin refresh token

Securitatea este gestionată printr-un refresh token, ceea ce înseamnă că nu trebuie să stochezi username/parolă în clar. Scriptul obține un access token temporar, valabil pentru operațiile API.

$Result = Invoke-RestMethod -Method Post -Uri "$($auth_url)?refresh_token=$($refresh_token)&client_id=$($client_id)&client_secret=$($client_secret)&grant_type=refresh_token"

📁 Structura fișierelor generate

Fiecare backup se salvează automat în:

X:\Zoho Analytics\<zi.luna.an>\<workspace_name>-<workspace_id>\<table_name>-<view_id>.csv

Astfel, poți urmări ușor istoricul backupurilor și identifica rapid tabelele.

🔄 Workflow-ul complet

  1. ✅ Generează token de acces
  2. ✅ Apelează API-ul pentru a obține workspace-urile
  3. ✅ Pentru fiecare workspace, extrage doar tabelele (viewType = Table)
  4. ✅ Creează foldere pe disc local
  5. ✅ Salvează fiecare tabel ca fișier .csv
  6. ✅ Loghează fiecare pas, cu timestamp

📝 Logging centralizat

Tot ce se întâmplă este scris în:

X:\Zoho Analytics\backup_zoho_analytics.log

Asta îți permite să verifici ce s-a întâmplat chiar dacă scriptul a rulat automat (ex: în Task Scheduler sau cron job).

💡 De ce e util acest script?

  • ✅ Evită pierderea datelor importante din Zoho Analytics
  • ✅ Ideal pentru companii care trebuie să respecte politici de backup (ISO, GDPR etc.)
  • ✅ Oferă control complet asupra datelor tale, fără a depinde doar de Zoho

✅ Concluzie

Dacă folosești Zoho Analytics în compania ta, acest script PowerShell este un mod simplu și sigur de a face backup automat la datele din tabele.

E scalabil, documentat și ușor de personalizat. Poți rula scriptul zilnic, săptămânal sau lunar – după nevoile business-ului tău.


📩 Vrei să automatizăm și alte procese pentru compania ta?
Contactează TechLoop și îți oferim soluții personalizate, moderne, bazate pe open-source și cloud.


Leave a Reply

Your email address will not be published. Required fields are marked *