{"id":13710068,"url":"https://github.com/eeghor/mta","last_synced_at":"2025-12-14T09:06:22.767Z","repository":{"id":54179590,"uuid":"155513940","full_name":"eeghor/mta","owner":"eeghor","description":"Multi-Touch Attribution","archived":false,"fork":false,"pushed_at":"2025-11-11T04:26:45.000Z","size":361,"stargazers_count":117,"open_issues_count":1,"forks_count":36,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-11-11T06:17:35.838Z","etag":null,"topics":["marketing","markov-model","probabilistic-models","shapley"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eeghor.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-10-31T07:08:10.000Z","updated_at":"2025-11-11T04:26:48.000Z","dependencies_parsed_at":"2022-08-13T08:30:59.155Z","dependency_job_id":null,"html_url":"https://github.com/eeghor/mta","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/eeghor/mta","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eeghor%2Fmta","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eeghor%2Fmta/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eeghor%2Fmta/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eeghor%2Fmta/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eeghor","download_url":"https://codeload.github.com/eeghor/mta/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eeghor%2Fmta/sbom","scorecard":{"id":367887,"data":{"date":"2025-08-11","repo":{"name":"github.com/eeghor/mta","commit":"e204b8b1370c2adf9cab19c13fbde0b02fb491f9"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.6,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-18T12:17:37.705Z","repository_id":54179590,"created_at":"2025-08-18T12:17:37.705Z","updated_at":"2025-08-18T12:17:37.705Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27724210,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-12-14T02:00:11.348Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["marketing","markov-model","probabilistic-models","shapley"],"created_at":"2024-08-02T23:00:51.477Z","updated_at":"2025-12-14T09:06:22.761Z","avatar_url":"https://github.com/eeghor.png","language":"Python","funding_links":[],"categories":["Attribution"],"sub_categories":[],"readme":"# Multi-Touch Attribution (MTA)\n\nA comprehensive Python library for multi-touch attribution modeling in marketing analytics. This library implements various attribution models to help marketers understand the contribution of different touchpoints in the customer journey.\n\n## 🎯 Features\n\n### Attribution Models Implemented\n\n- **First Touch**: 100% credit to the first interaction\n- **Last Touch**: 100% credit to the last interaction before conversion\n- **Linear**: Equal credit distribution across all touchpoints\n- **Position-Based (U-Shaped)**: Customizable weights for first/last touch with remaining credit distributed to middle touches\n- **Time Decay**: Higher credit to more recent touchpoints\n- **Markov Chain**: Probabilistic model using transition matrices\n- **Shapley Value**: Game-theoretic fair allocation based on marginal contributions\n- **Shao's Model**: Probabilistic Shapley-equivalent approach\n- **Logistic Regression**: Machine learning-based ensemble attribution\n- **Additive Hazard**: Survival analysis-based attribution\n\n## 📦 Installation\n\n```bash\npip install mta\n```\n\nOr install from source:\n\n```bash\ngit clone https://github.com/eeghor/mta.git\ncd mta\npip install -e .\n```\n\n## 🚀 Quick Start\n\n### Basic Usage\n\n```python\nfrom mta import MTA\n\n# Initialize with your data\nmta = MTA(data=\"your_data.csv\", allow_loops=False, add_timepoints=True)\n\n# Run a single attribution model\nmta.linear(share=\"proportional\", normalize=True)\nmta.show()\n\n# Chain multiple models\n(mta.linear(share=\"proportional\")\n    .time_decay(count_direction=\"right\")\n    .markov(sim=False)\n    .shapley()\n    .show())\n```\n\n### Using Configuration\n\n```python\nfrom mta import MTA, MTAConfig\n\n# Create custom configuration\nconfig = MTAConfig(\n    allow_loops=False,\n    add_timepoints=True,\n    sep=\" \u003e \",\n    normalize_by_default=True\n)\n\nmta = MTA(data=\"data.csv\", config=config)\n```\n\n### Working with DataFrames\n\n```python\nimport pandas as pd\nfrom mta import MTA\n\n# Load your data\ndf = pd.read_csv(\"customer_journeys.csv\")\n\n# Initialize MTA with DataFrame\nmta = MTA(data=df, allow_loops=False)\n\n# Run attribution models\nmta.first_touch().last_touch().linear().show()\n```\n\n## 📊 Data Format\n\nYour input data should be a CSV file or pandas DataFrame with the following columns:\n\n```\npath,total_conversions,total_null,exposure_times\nalpha \u003e beta \u003e gamma,10,5,2023-01-01 10:00:00 \u003e 2023-01-01 11:00:00 \u003e 2023-01-01 12:00:00\nbeta \u003e gamma,5,3,2023-01-02 09:00:00 \u003e 2023-01-02 10:00:00\n```\n\n**Required Columns:**\n\n- `path`: Customer journey as channel names separated by `\u003e` (or custom separator)\n- `total_conversions`: Number of conversions for this path\n- `total_null`: Number of non-conversions for this path\n- `exposure_times`: Timestamps of channel exposures (optional, can be auto-generated)\n\n## 🎨 Advanced Usage\n\n### Position-Based Attribution with Custom Weights\n\n```python\n# Give 30% to first touch, 30% to last touch, 40% distributed to middle\nmta.position_based(first_weight=30, last_weight=30, normalize=True)\n```\n\n### Time Decay with Direction Control\n\n```python\n# Count from left (earliest gets lowest credit)\nmta.time_decay(count_direction=\"left\")\n\n# Count from right (latest gets highest credit - more common)\nmta.time_decay(count_direction=\"right\")\n```\n\n### Markov Chain Attribution\n\n```python\n# Analytical calculation (faster)\nmta.markov(sim=False, normalize=True)\n\n# Simulation-based (more flexible, handles complex scenarios)\nmta.markov(sim=True, normalize=True)\n```\n\n### Shapley Value Attribution\n\n```python\n# With custom coalition size\nmta.shapley(max_coalition_size=3, normalize=True)\n```\n\n### Logistic Regression Ensemble\n\n```python\n# Custom sampling and iteration parameters\nmta.logistic_regression(\n    test_size=0.25,\n    sample_rows=0.5,\n    sample_features=0.5,\n    n_iterations=1000,\n    normalize=True\n)\n```\n\n### Export Results\n\n```python\n# Compare all models\nresults_df = mta.compare_models()\n\n# Export to various formats\nmta.export_results(\"attribution_results.csv\", format=\"csv\")\nmta.export_results(\"attribution_results.json\", format=\"json\")\nmta.export_results(\"attribution_results.xlsx\", format=\"excel\")\n```\n\n## 📈 Example: Complete Analysis Pipeline\n\n```python\nfrom mta import MTA\nimport pandas as pd\n\n# Load data\nmta = MTA(\n    data=\"customer_journeys.csv\",\n    allow_loops=False,  # Remove consecutive duplicate channels\n    add_timepoints=True  # Auto-generate timestamps if missing\n)\n\n# Run all heuristic models\n(mta\n    .first_touch()\n    .last_touch()\n    .linear(share=\"proportional\")\n    .position_based(first_weight=40, last_weight=40)\n    .time_decay(count_direction=\"right\"))\n\n# Run algorithmic models\n(mta\n    .markov(sim=False)\n    .shapley(max_coalition_size=2)\n    .shao()\n    .logistic_regression(n_iterations=2000)\n    .additive_hazard(epochs=20))\n\n# Display and export results\nresults = mta.compare_models()\nmta.export_results(\"full_attribution_analysis.csv\")\n\n# Access specific model results\nprint(f\"Markov Attribution: {mta.attribution['markov']}\")\nprint(f\"Shapley Attribution: {mta.attribution['shapley']}\")\n```\n\n## 🔬 Model Comparison\n\n| Model               | Type             | Strengths                | Use Case                     |\n| ------------------- | ---------------- | ------------------------ | ---------------------------- |\n| First/Last Touch    | Heuristic        | Simple, fast             | Quick baseline               |\n| Linear              | Heuristic        | Fair, interpretable      | Equal value assumption       |\n| Position-Based      | Heuristic        | Balances first/last      | Awareness + conversion focus |\n| Time Decay          | Heuristic        | Recency-weighted         | When recent matters more     |\n| Markov Chain        | Algorithmic      | Considers path structure | Sequential dependency        |\n| Shapley Value       | Algorithmic      | Game-theoretic fairness  | Complex interactions         |\n| Logistic Regression | Machine Learning | Data-driven              | Large datasets               |\n| Additive Hazard     | Statistical      | Time-to-event modeling   | Survival analysis fans       |\n\n## 🛠️ Requirements\n\n- Python \u003e= 3.8\n- pandas \u003e= 1.3.0\n- numpy \u003e= 1.20.0\n- scikit-learn \u003e= 0.24.0\n- arrow \u003e= 1.0.0\n\n## 📝 Citation\n\nIf you use this library in your research, please cite:\n\n```bibtex\n@software{mta2024,\n  author = {Igor Korostil},\n  title = {MTA: Multi-Touch Attribution Library},\n  year = {2024},\n  url = {https://github.com/eeghor/mta}\n}\n```\n\n## 📚 References\n\nThis library implements models and techniques from the following research papers:\n\n1. **Nisar, T. M., \u0026 Yeung, M. (2015)**  \n   _Purchase Conversions and Attribution Modeling in Online Advertising: An Empirical Investigation_  \n   [PDF](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=2612997)\n\n2. **Shao, X., \u0026 Li, L. (2011)**  \n   _Data-driven Multi-touch Attribution Models_  \n   Proceedings of the 17th ACM SIGKDD International Conference on Knowledge Discovery and Data Mining  \n   [PDF](https://dl.acm.org/doi/10.1145/2020408.2020453)\n\n3. **Dalessandro, B., Perlich, C., Stitelman, O., \u0026 Provost, F. (2012)**  \n   _Causally Motivated Attribution for Online Advertising_  \n   Proceedings of the Sixth International Workshop on Data Mining for Online Advertising  \n   [PDF](https://dl.acm.org/doi/10.1145/2351356.2351363)\n\n4. **Cano-Berlanga, S., Giménez-Gómez, J. M., \u0026 Vilella, C. (2017)**  \n   _Attribution Models and the Cooperative Game Theory_  \n   Expert Systems with Applications, 87, 277-286  \n   [PDF](https://www.sciencedirect.com/science/article/abs/pii/S0957417417304505)\n\n5. **Ren, K., Fang, Y., Zhang, W., Liu, S., Li, J., Zhang, Y., Yu, Y., \u0026 Wang, J. (2018)**  \n   _Learning Multi-touch Conversion Attribution with Dual-attention Mechanisms for Online Advertising_  \n   Proceedings of the 27th ACM International Conference on Information and Knowledge Management  \n   [PDF](https://dl.acm.org/doi/10.1145/3269206.3271676)\n\n6. **Zhang, Y., Wei, Y., \u0026 Ren, J. (2014)**  \n   _Multi-Touch Attribution in Online Advertising with Survival Theory_  \n   2014 IEEE International Conference on Data Mining  \n   [PDF](https://ieeexplore.ieee.org/document/7023387)\n\n7. **Geyik, S. C., Saxena, A., \u0026 Dasdan, A. (2014)**  \n   _Multi-Touch Attribution Based Budget Allocation in Online Advertising_  \n   Proceedings of the 8th International Workshop on Data Mining for Online Advertising  \n   [PDF](https://dl.acm.org/doi/10.1145/2648584.2648586)\n\n### Model-to-Paper Mapping\n\n- **Linear \u0026 Position-Based**: Baseline models referenced across multiple papers\n- **Time Decay**: Nisar \u0026 Yeung (2015), Zhang et al. (2014)\n- **Markov Chain**: Shao \u0026 Li (2011), Dalessandro et al. (2012)\n- **Shapley Value**: Cano-Berlanga et al. (2017)\n- **Logistic Regression**: Dalessandro et al. (2012), Ren et al. (2018)\n- **Additive Hazard**: Zhang et al. (2014)\n\n## 🤝 Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n## 📄 License\n\nThis project is licensed under the MIT License - see the LICENSE file for details.\n\n## 🙏 Acknowledgments\n\n- Inspired by various academic papers on marketing attribution\n- Built with pandas, numpy, and scikit-learn\n- Special thanks to the open-source community\n\n## 📧 Contact\n\nIgor Korostil - eeghor@gmail.com\n\nProject Link: [https://github.com/eeghor/mta](https://github.com/eeghor/mta)\n\n## 🐛 Known Issues\n\n- Shapley value computation can be slow for large numbers of channels\n- Additive hazard model requires evenly-spaced time points for best results\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feeghor%2Fmta","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feeghor%2Fmta","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feeghor%2Fmta/lists"}